Python面向?qū)ο缶幊袒A(chǔ)實(shí)例分析
本文實(shí)例講述了Python面向?qū)ο缶幊袒A(chǔ)。分享給大家供大家參考,具體如下:
1、類的定義
Python中類的定義與對(duì)象的初始化如下,python中所有類的父類是object,需要繼承。
由于Python是動(dòng)態(tài)語言,因此可以直接為對(duì)象添加屬性并賦值而不必在類定義中聲明
class Person(object): # 定義一個(gè)Person類 pass p = Person() # 初始化一個(gè)Person對(duì)象 p.name="xiaoming" # 對(duì)象屬性賦值
Python的類初始化方法為__init__(),其第一個(gè)參數(shù)為self代之對(duì)象自身,其后為各個(gè)參數(shù),初始化就是將傳入的參數(shù)賦值給對(duì)象的屬性。**kw代表任意數(shù)量的屬性,通過key=attribute的形式傳入,之后通過setattr()方法將每個(gè)屬性賦值給對(duì)象。
直接在class中定義的變量稱為類屬性,在__init__()中定義的為對(duì)象屬性,類屬性供所有對(duì)象共享,對(duì)象只能訪問卻無權(quán)修改。當(dāng)通過對(duì)象給類屬性賦值時(shí),會(huì)為對(duì)象新建一個(gè)同名的對(duì)象屬性,而不是修改類屬性。無論在類的內(nèi)部還是外部,都通過類名對(duì)類屬性進(jìn)行訪問。
以__開頭的變量無法被外部訪問,類似于私有變量。這時(shí)就需要對(duì)象的實(shí)例方法從類的內(nèi)部訪問私有變量并做出相應(yīng)的操作,這樣在類的內(nèi)部定義的方法叫做實(shí)例方法,實(shí)例方法的第一個(gè)參數(shù)默認(rèn)為self代表對(duì)象自己。
相應(yīng)地類方法只能訪問類屬性,其定義方式是在之前添加標(biāo)記@classmethod:,其第一個(gè)參數(shù)cls代表類本身
class Person(object): count = 0 # 類屬性 @classmethod: def get_count(cls): # 類方法 return cls.count def __init__(self,name,gender,birth,**kw): Person.count+=1 # 訪問類屬性 self.name = name self.__gender = gender self.birth = birth for k, v in kw.iteritems(): # 遍歷之后的鍵值對(duì),設(shè)置屬性 setattr(self, k, v) def get_name(self): # 定義實(shí)例方法 return self.__name xiaoming = Person('Xiao Ming', 'Male', '1990-1-1', job='Student') xiaoming.count==9 # 為對(duì)象創(chuàng)建屬性,不會(huì)修改Person.count print(xiaoming.job) # 顯示Student print(xiaoming.__gender) # 無法訪問,拋出異常AttributeError print(xiaoming.get_name()) # 通過實(shí)例方法訪問內(nèi)部變量
2、類的繼承
Python中類的繼承方式如下。值得注意的是在子類Teacher中需要通過super(子類名,self)調(diào)用父類的初始化函數(shù)來完成對(duì)父類中參數(shù)的初始化。也可以直接通過父類名稱調(diào)用父類的方法
通過type()方法輸出變量的類型,isinstance()可以判斷變量是否是某個(gè)類型,dir()方法返回變量的所有屬性和方法列表。輸出對(duì)象t的屬性結(jié)果如下,其中帶__的為默認(rèn)屬性,其余為自定義的屬性
['__class__', '__delattr__', '__dict__', '__dir__', '__doc__', '__eq__', '__format__', '__ge__', '__getattribute__', '__gt__', '__hash__', '__init__', '__init_subclass__', '__le__', '__lt__', '__module__', '__ne__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__sizeof__', '__str__', '__subclasshook__', '__weakref__', 'course', 'gender', 'name']
class Person(object): def __init__(self, name, gender): self.name = name self.gender = gender class Teacher(Person): # 繼承父類Person def __init__(self, name, gender, course): super(Teacher,self).__init__(name,gender) # 調(diào)用父類的初始化函數(shù) self.course= course # 完成子類變量的初始化 t = Teacher('Alice', 'Female', 'English') print(isinstance(t,Person)) # 結(jié)果為True,子類也是父類的類型 print(dir(t)) # 顯示對(duì)象的所有屬性
和其他面向?qū)ο蟮恼Z言一樣,Python具有多態(tài)的特性,例如父類和不同的子類都定義了相同的方法,當(dāng)不同的子類調(diào)用該方法時(shí)會(huì)調(diào)用自己定義的方法,從而實(shí)現(xiàn)相同的方法具有不同的操作。但python是動(dòng)態(tài)語言,和靜態(tài)語言C++、Java不同的是在調(diào)用實(shí)例方法時(shí),python不檢查類型,只要方法存在,參數(shù)正確,就可以調(diào)用。例如原本json的load方法中定義了read()方法用于實(shí)現(xiàn)對(duì)文件的讀取,當(dāng)我們自定義一個(gè)類其中包含read()方法時(shí),便可動(dòng)態(tài)調(diào)用實(shí)例方法
import json class Students(object): def read(self): return r'["Tim", "Bob", "Alice"]' s = Students() print json.load(s)
一個(gè)子類可以同時(shí)繼承兩個(gè)以上的父類,這個(gè)特性叫做多繼承,當(dāng)有多個(gè)父類時(shí),需要在初始化時(shí)指明父類
class A(object): def __init__(self, a): self.a = a class B(object): def __init__(self, b): self.b = b class C(A, B): def __init__(self, a, b, c): A.__init__(self, a) B.__init__(self, b) self.c = c c = C(1, 2, 3) print(c.a) # 輸出1
3、類的特殊方法
Python的特殊方法是指定義在類中,以__開頭和結(jié)尾,由某些函數(shù)或操作符隱式觸發(fā)調(diào)用的方法。例如當(dāng)我們使用print(p)打印一個(gè)Person對(duì)象p時(shí),就會(huì)調(diào)用Person的__str__()方法將p轉(zhuǎn)化為字符串共print輸出,輸出結(jié)果為:<__main__.Person object at 0x000001787CC7C0D0>
當(dāng)我們重新自定義這些特殊方法后,當(dāng)觸發(fā)調(diào)用時(shí)就會(huì)按我們定義的函數(shù)執(zhí)行。例如重新定義__str__(),當(dāng)print()時(shí)就會(huì)顯示My name is Bob
class Person(object): def __init__(self, name, gender): self.name = name self.gender = gender def __str__(self): # 重新定義類特殊方法 return "My name is " + self.name p = Person('Bob', 'male') print(p) # 輸出結(jié)果為:My name is Bob
__cmp__()方法用于實(shí)現(xiàn)類的比較,在排序時(shí)會(huì)自動(dòng)調(diào)用。例如在Student類中重新定義該方法,按分?jǐn)?shù)高低對(duì)學(xué)生進(jìn)行排序,其有兩個(gè)參數(shù),第一個(gè)自己self,第二個(gè)是比較的對(duì)象s,如果self應(yīng)該在s之前,則返回-1
class Student(object): def __init__(self, name, score): self.name = name self.score = score def __cmp__(self, s): # 重寫__cmp__方法 if self.score>s.score: return -1 # self在s之前 elif self.score<s.score: return 1 else: return 0 L = [Student('Tim', 99), Student('Bob', 88), Student('Alice', 99)] Ls = sorted(L) # 使用sorted對(duì)Student類進(jìn)行排序
__len__()方法用于返回長度,當(dāng)len()調(diào)用類時(shí)會(huì)觸發(fā)
__add__、__sub__、__mul__、__div__分別對(duì)應(yīng)類的加減乘除運(yùn)算,當(dāng)類遇到運(yùn)算符+-*/時(shí)會(huì)調(diào)用該方法,例如實(shí)現(xiàn)一個(gè)分?jǐn)?shù)類Rational的加法:1/2+1/4,通分相加得6/8,最后求最大公約數(shù)后約分得到3/4
__int__、__float__方法在int()、float()調(diào)用類時(shí)觸發(fā),可以重新該方法返回一個(gè)int或float結(jié)果
def gcd(a, b): # 求最大公約數(shù) if b == 0: return a return gcd(b, a % b) class Rational(object): def __init__(self, p, q): self.p = p self.q = q def __add__(self, r): # 重寫加法運(yùn)算 return Rational(self.p * r.q + self.q * r.p, self.q * r.q) def __str__(self): g = gcd(self.p, self.q) # 將分?jǐn)?shù)約分后輸出 return '%s/%s' % (self.p / g, self.q / g) def __float__(self): # 將分?jǐn)?shù)轉(zhuǎn)化為float小數(shù)返回 return float(self.p)/float(self.q) r1 = Rational(1, 2) r2 = Rational(1, 4) print(r1 + r2) # 兩個(gè)類相加 print(float(r1)) # 輸出小數(shù)形式
類屬性的裝飾器@property用于將類方法轉(zhuǎn)化為屬性,這樣就可以像訪問屬性一樣調(diào)用方法。例如Student類的__score屬性對(duì)外是不可見的,通過定義返回方法score使得對(duì)象s可以通過s.score得到分?jǐn)?shù)值。
@property.setter方法用于對(duì)屬性設(shè)置方法進(jìn)行裝飾,使得可以像給屬性賦值一樣調(diào)用類方法。例如當(dāng)使用s.score=99時(shí)會(huì)調(diào)用設(shè)置方法score(self,score),將值傳遞給__score,并且可以對(duì)傳入值的合法性進(jìn)行檢驗(yàn)。
__slots__()用于定義類中可以使用的屬性,父類定義過的子類中無需重復(fù)定義。當(dāng)添加新的屬性并賦值時(shí),運(yùn)行會(huì)拋出異常AttributeError
__call__()將一個(gè)類實(shí)例變成一個(gè)可調(diào)用對(duì)象,例如一個(gè)Student對(duì)象s,像函數(shù)調(diào)用一樣使用對(duì)象:s('Alice')
class Student(object): __slots__ = ('name','__score') # 本類只允許使用name、score兩個(gè)屬性 def __init__(self, name, score): self.name = name self.__score = score @property # 定義屬性返回方法 def score(self): return self.__score @score.setter # 定義屬性設(shè)置方法 def score(self, score): if score < 0 or score > 100: raise ValueError('invalid score') self.__score = score def __call__(self, friend): print('My friend is %s...' % friend) s = Student('Bob', 59) s.score = 60 # 調(diào)用屬性設(shè)置方法 print(s.score) # 調(diào)用屬性返回方法 s.grade='A' # 拋出異常,無法添加其他屬性 s('Alice') # 輸出My friend is Alice...
__getattribute__(self,attr)、__setattr__(self,attr)、__delattr__(self,attr)分別用于獲取、設(shè)置、刪除屬性時(shí)觸發(fā)的方法,在使用時(shí)應(yīng)注意避免遞歸調(diào)用引起的無限循環(huán),例如在get方法中再調(diào)用get類似的方法導(dǎo)致無限循環(huán)。
4、模塊管理
為了方便分類管理python中的類和方法,需要將代碼放在不同的文件中,每個(gè)文件構(gòu)成了一個(gè)獨(dú)立的模塊,不同模塊之間相同的變量名不會(huì)引起命名沖突。但是如果在文件a.py中希望使用文件b.py中的函數(shù)func1,則可以通過import在a中導(dǎo)入模塊b,并通過b.func1()調(diào)用該方法?;蛘咄ㄟ^from直接引入模塊中的函數(shù)。在引入時(shí)為了防止命名沖突,可以通過as為引入的函數(shù)起個(gè)別名
# 文件a.py中 import b print(b.func1()) # 直接引入函數(shù) from b import func1 print(func1()) # 使用別名 from b import func1 as f1 print(f1())
有時(shí)將相同類別的模塊放在一個(gè)文件夾內(nèi),就形成了一個(gè)包,python要求一個(gè)包文件夾內(nèi)必須有一個(gè)__init__.py文件才會(huì)識(shí)別為一個(gè)包,即使它是一個(gè)空文件。這時(shí)如果一個(gè)p1包內(nèi)的a.py想訪問p2包內(nèi)的b.py中的函數(shù)func2,則操作如下
# p1/a.py文件內(nèi) import p2.b print (p2.b.func2())
更多關(guān)于Python相關(guān)內(nèi)容感興趣的讀者可查看本站專題:《Python面向?qū)ο蟪绦蛟O(shè)計(jì)入門與進(jìn)階教程》、《Python數(shù)據(jù)結(jié)構(gòu)與算法教程》、《Python函數(shù)使用技巧總結(jié)》、《Python字符串操作技巧匯總》、《Python編碼操作技巧總結(jié)》及《Python入門與進(jìn)階經(jīng)典教程》
希望本文所述對(duì)大家Python程序設(shè)計(jì)有所幫助。
相關(guān)文章
Python數(shù)據(jù)結(jié)構(gòu)與算法之鏈表定義與用法實(shí)例詳解【單鏈表、循環(huán)鏈表】
這篇文章主要介紹了Python數(shù)據(jù)結(jié)構(gòu)與算法之鏈表定義與用法,結(jié)合具體實(shí)例形式較為詳細(xì)的分析了單鏈表、循環(huán)鏈表等的定義、使用方法與相關(guān)注意事項(xiàng),需要的朋友可以參考下2017-09-09python回調(diào)函數(shù)用法實(shí)例分析
這篇文章主要介紹了python回調(diào)函數(shù)用法,較為詳細(xì)的分析了常用的調(diào)用方式,并實(shí)例介紹了Python回調(diào)函數(shù)的使用技巧,需要的朋友可以參考下2015-05-05python3格式化字符串 f-string的高級(jí)用法(推薦)
從Python 3.6開始,f-string是格式化字符串的一種很好的新方法。與其他格式化方式相比,它們不僅更易讀,更簡潔,不易出錯(cuò),而且速度更快!本文重點(diǎn)給大家介紹python3格式化字符串 f-string的高級(jí)用法,一起看看吧2020-03-03詳解Python 數(shù)據(jù)庫 (sqlite3)應(yīng)用
本篇文章主要介紹了Python標(biāo)準(zhǔn)庫14 數(shù)據(jù)庫 (sqlite3),小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過來看看吧。2016-12-12用Python和WordCloud繪制詞云的實(shí)現(xiàn)方法(內(nèi)附讓字體清晰的秘笈)
這篇文章主要介紹了用Python和WordCloud繪制詞云的實(shí)現(xiàn)方法(內(nèi)附讓字體清晰的秘笈),文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2019-01-01Python中__str__()方法的實(shí)用技巧分享
在Python編程中,__str__()是一個(gè)特殊方法,它允許自定義對(duì)象的字符串表示形式,本文將深入探討__str__()的相關(guān)實(shí)用技巧,希望對(duì)大家有所幫助2023-11-11