第25章-OOP:宏偉藍(lán)圖
為何使用類
與其他程序組成單元相比,類有三個(gè)獨(dú)到之處:
- 多重實(shí)例:類基本上就是生產(chǎn)對(duì)象的工廠,每次調(diào)用一個(gè)類,都有獨(dú)立命名空間的新對(duì)象葫督。
- 通過(guò)繼承進(jìn)行定制:類也支持OPP的繼承的概念。
- 運(yùn)算符重載:通過(guò)提供特定的協(xié)議方法板惑,類可以重載運(yùn)算符橄镜。
第26章-類代碼編寫(xiě)基礎(chǔ)
類產(chǎn)生多個(gè)實(shí)例
- 類對(duì)象和實(shí)例對(duì)象各自有獨(dú)立的命名空間。
- 說(shuō)白了類就是實(shí)例的工廠函數(shù)
類對(duì)象提供默認(rèn)行為
- class語(yǔ)句創(chuàng)建類對(duì)象并將其復(fù)制給變量名
- class語(yǔ)句內(nèi)的賦值語(yǔ)句會(huì)創(chuàng)建類的屬性
- 類屬性提供對(duì)象的狀態(tài)和行為
實(shí)例是具體的元素
- 像函數(shù)那樣調(diào)用類對(duì)象會(huì)創(chuàng)建新的實(shí)例對(duì)象
- 每個(gè)實(shí)例對(duì)象繼承類的屬性并獲得了自己的命名空間
- 在方法內(nèi)懟self屬性做賦值運(yùn)算會(huì)產(chǎn)生每個(gè)實(shí)例自己的屬性
注意:
- 可以對(duì)實(shí)例的直接賦值
類可以截獲python運(yùn)算符
- 以雙下劃線命名的方法都是特殊鉤子洒放,可以用來(lái)攔截運(yùn)算
- 當(dāng)實(shí)例出現(xiàn)在內(nèi)置運(yùn)算時(shí)蛉鹿,這類方法會(huì)自動(dòng)調(diào)用(指上述雙下劃線的方法)
- 類可以覆蓋多數(shù)內(nèi)置類型運(yùn)算
- 運(yùn)算符覆蓋方法沒(méi)有默認(rèn)值滨砍,而且也不需要
- 運(yùn)算符可讓類與python的對(duì)象模型相繼承
In [294]: class rec:pass
In [295]: rec.name='damao'
In [296]: rec.age=18
In [297]: rec.name
Out[297]: 'damao'
In [298]: x=rec()
In [299]: x.age
Out[299]: 18
In [300]: x.name
Out[300]: 'damao'
In [301]: rec.__dict__
Out[301]:
mappingproxy({'__module__': '__main__',
'__dict__': <attribute '__dict__' of 'rec' objects>,
'__weakref__': <attribute '__weakref__' of 'rec' objects>,
'__doc__': None,
'name': 'damao',
'age': 18})
In [302]: x.__dict__
Out[302]: {}
第27章 更多實(shí)例
第28章 類代碼編寫(xiě)細(xì)節(jié)
- class是創(chuàng)建并且隱式賦值往湿,并不是聲明
- 注意。類可以通過(guò)直接賦值來(lái)改變屬性值的惋戏。
In [303]: class ShareData:
...: spam=42
...:
In [304]: x=ShareData()
In [305]: y=ShareData()
In [306]: x.spam
Out[306]: 42
In [307]: y.spam
Out[307]: 42
In [308]: ShareData.spam=24
In [309]: x.spam
Out[309]: 24
In [310]: y.spam
Out[310]: 24
In [311]: x.spam=100
In [312]: x.spam
Out[312]: 100
In [313]: y.spam
Out[313]: 24
In [314]: ShareData.spam
Out[314]: 24
注意领追,在構(gòu)造時(shí),python只會(huì)找出并且調(diào)用一個(gè)
__init__
類的方法上如果使用了@abstractmethod响逢,那么這個(gè)類不能被實(shí)例話绒窑,它的子類如果沒(méi)有實(shí)現(xiàn)fun方法,也不能被實(shí)例化舔亭。
# 其中11是模塊屬性些膨,22是函數(shù)內(nèi)本地變量蟀俊,33是類屬性,44是方法中本地變量订雾,55是實(shí)例屬性
In [320]: X=11
...:
...: def f():
...: print(X)
...:
...: def g():
...: X=22
...: print(X)
...:
...: class C:
...: X=33
...: def m(self):
...: X=44
...: self.X=55
...:
In [321]:
In [321]: print(X)
11
In [322]: f()
11
In [323]: g()
22
In [324]: print(X)
11
In [325]: obj=C()
In [326]: obj.X
Out[326]: 33
In [327]: obj.m()
In [328]: obj.x
---------------------------------------------------------------------------
AttributeError Traceback (most recent call last)
<ipython-input-328-b69ab213b68b> in <module>()
----> 1 obj.x
AttributeError: 'C' object has no attribute 'x'
In [329]: obj.X
Out[329]: 55
In [330]: C.X
Out[330]: 33
In [331]: C.m.X
---------------------------------------------------------------------------
AttributeError Traceback (most recent call last)
<ipython-input-331-68ecbd26cef2> in <module>()
----> 1 C.m.X
AttributeError: 'function' object has no attribute 'X'
In [332]: g.X
---------------------------------------------------------------------------
AttributeError Traceback (most recent call last)
<ipython-input-332-a8d85d587c9b> in <module>()
----> 1 g.X
AttributeError: 'function' object has no attribute 'X'
In [333]: obj.m.__dict__
Out[333]: {}
# 打印繼承樹(shù)
def classtree(cls, indent):
print('.' * indent, cls.__name__)
for supercls in cls.__bases__:
classtree(supercls, indent + 3)
def instancetree(inst):
print('Tree of %s' % inst)
classtree(inst.__class__, 3)
def selftest():
class A: pass
class B(A): pass
class C(A): pass
class D(B, C): pass
class E: pass
class F(D, E): pass
instancetree(B())
instancetree(F())
第29章 運(yùn)算符重載
運(yùn)算符的重載其實(shí)就是一種攔截肢预。
# 定義__getitem__之后立馬就支持了for循環(huán)
In [381]: class stepper:
...: def __getitem__(self, item):
...: return self.data[item]
...:
...: X=stepper()
...:
...: X.data='Spam'
...:
...:
In [382]: X[1]
Out[382]: 'p'
In [383]: for item in X:
...: print(item)
...:
S
p
a
m
python中所有的迭代環(huán)境都會(huì)先嘗試__iter__
方法,再嘗試__getiterm__
方法洼哎。iter方法是返回一個(gè)迭代器烫映,而getiterm方法是獲取偏移量重復(fù)索引。
In [384]: class Squares:
...: def __init__(self, start, stop):
...: self.value = start - 1
...: self.stop = stop
...: # 返回本身噩峦,所以這種方法只支持一個(gè)迭代器
...: def __iter__(self):
...: return self
...:
...: def __next__(self):
...: if self.value == self.stop:
...: raise StopIteration
...: self.value += 1
...: return self.value ** 2
...:
In [385]:
In [385]: for i in Squares(1,5)
File "<ipython-input-385-7c699374acfb>", line 1
for i in Squares(1,5)
^
SyntaxError: invalid syntax
In [386]: for i in Squares(1,5):
...: print(i)
...:
1
4
9
16
25
In [387]: list(Squares)
---------------------------------------------------------------------------
TypeError Traceback (most recent call last)
<ipython-input-387-d7debed4f6f7> in <module>()
----> 1 list(Squares)
TypeError: 'type' object is not iterable
In [388]: list(Squares(1,6))
Out[388]: [1, 4, 9, 16, 25, 36]
In [389]: X=Squares(1,5)
In [390]: I=iter(X)
In [391]: next(I)
Out[391]: 1
In [392]: next(I)
Out[392]: 4
In [393]: next(I)
Out[393]: 9
In [394]: next(I)
Out[394]: 16
In [395]: next(I)
Out[395]: 25
In [396]: next(I)
---------------------------------------------------------------------------
StopIteration Traceback (most recent call last)
<ipython-input-396-ebc5a6f5e444> in <module>()
----> 1 next(I)
<ipython-input-384-6f8e42cd1b09> in __next__(self)
9 def __next__(self):
10 if self.value == self.stop:
---> 11 raise StopIteration
12 self.value += 1
13 return self.value ** 2
StopIteration:
- 雙下劃線開(kāi)頭的變量名會(huì)自動(dòng)擴(kuò)張锭沟,比如
__spam
,將擴(kuò)展成_x__spam
In [400]: class C1:
...: def meth1(self):self.__X=88
...: def meth2(self):print(self.__X)
...:
...: class C2:
...: def metha(self):self.__X=99
...: def methb(self):print(self.__X)
...:
...: class C3(C1,C2):pass
...:
...:
In [401]: I=C3()
In [402]:
In [402]: I.meth1()
In [403]: I.metha()
# 注意這個(gè)地方 值沒(méi)有被覆蓋了识补,跟下面做對(duì)比
In [404]: I.__dict__
Out[404]: {'_C1__X': 88, '_C2__X': 99}
In [405]: I.meth2()
88
In [406]: I.methb()
99
In [407]: class C1:
...: def meth1(self):self.X=88
...: def meth2(self):print(self.X)
...:
...: class C2:
...: def metha(self):self.X=99
...: def methb(self):print(self.X)
...:
...: class C3(C1,C2):pass
...:
...: I=C3()
...:
...:
In [408]: I.meth1()
In [409]: I.metha()
# 注意這個(gè)地方 值被覆蓋了
In [410]: I.__dict__
Out[410]: {'X': 99}
In [411]: I.meth2()
99
In [412]: I.methb()
99