国产探花免费观看_亚洲丰满少妇自慰呻吟_97日韩有码在线_资源在线日韩欧美_一区二区精品毛片,辰东完美世界有声小说,欢乐颂第一季,yy玄幻小说排行榜完本

首頁 > 學院 > 開發設計 > 正文

《Python基礎教程》讀書筆記第九章魔法方法、屬性和迭代器(上)

2019-11-14 17:09:51
字體:
來源:轉載
供稿:網友

構造方法

 

在Python中創建一個構造方法很容易。只要把init方法的名字從簡單的init修改為魔法版本__init__即可:

>>> class FooBar:

...     def __init__(self):

...         self.somevar=42

...        

>>> f=FooBar()

>>> f.somevar

42

給構造方法傳幾個參數

>>> class FooBar:

...     def __init__(self,value=42):

...         self.somevar=value

...        

>>> f=FooBar('this is a constructor argument')

>>> f.somevar

'this is a constructor argument'

 

重寫一般方法和特殊的構造方法

 

構造方法用來初始化新創建對象的狀態,大多數子類不僅要擁有自己的初始化代碼,還要擁有超類的初始化代碼。雖然重寫的機制對于所有方法來說都是一樣的,但是當處理構造方法比重寫普通方法時,更可能遇到特別的問題:如果一個類的構造方法被重寫,那么就需要調用超類(你所繼承的類)的構造方法,否則對象可能不會被正確地初始化。

>>> class Bird:

...     def __init__(self):

...         self.hungry=True

...     def eat(self):

...         if self.hungry:

...            

...             self.hungry=False

...         else:

...             print 'no thanks'

...  

>>> b=Bird()

>>> b.eat()

aaah...

>>> b.eat()

no thanks

鳥吃過了以后,它就不再饑餓。現在考慮子類SongBird,它添加了唱歌的行為:

>>> class SongBird(Bird):

...     def __init__(self):

...         self.sound='Squawk'

...     def sing(self):

...         print self.sound

...        

>>> s=SongBird()

>>> s.sing()

Squawk

因為SongBird是Bird的一個子類,它繼承了eat方法,但如果調用eat方法,就會產生一個問題:

>>> s.eat()

Traceback (most recent call last):

 File "<input>", line 1, in <module>

 File "<input>", line 5, in eat

AttributeError: SongBird instance has no attribute 'hungry'

錯誤:SongBird沒有hungry特性。原因是這樣的:在SongBird中,構造方法被重寫,但新的構造方法沒有任何關于初始化hungry特性的代碼。為了達到預期的效果,SongBird的構造方法必須調用其超類Bird的構造方法來確保進行基本的初始化。有兩種方法能達到這個目的:調用超類構造方法的未綁定版本,或者使用super函數。

 

調用未綁定的超類構造方法

 

>>> class SongBird(Bird):

...     def __init__(self):

...         Bird.__init__(self)

...         self.sound='Squawk'

...     def sing(self):

...         print self.sound

...        

>>> s=SongBird()

>>> s.eat()

aaah...

>>> s.eat()

no thanks

>>> s.sing()

Squawk

在調用一個實例的方法時,該方法的self參數會被自動綁定到實例上(這稱為綁定方法)。但如果直接調用類的方法(比如Bird.__init__),那么就沒有實例會被綁定。這樣就可以自由地提供需要的self參數。這樣的方法稱為未綁定(unbound)方法

 

使用super函數

 

當前的類和對象可以作為super函數的參數使用,調用函數返回的對象的任何方法都是調用超類的方法,而不是當前類的方法。

>>> __metaclass__=type

>>> class Bird:

...     def __init__(self):

...         self.hungry=True

...     def eat(self):

...         if self.hungry:

...             print 'aaah...'

...             self.hungry=False

...         else:

...             print 'no thanks'

...            

>>> class SongBird(Bird):

...     def __init__(self):

...         super(SongBird,self).__init__()

...         self.sound='Squawk'

...     def sing(self):

...         print self.sound

...  

這個新式的版本的運行結果和舊式版本的一樣      

>>> s=SongBird()

>>> s.sing()

Squawk

>>> s.eat()

aaah...

>>> s.eat()

no thanks

 

基本的序列和映射規則

 

序列和映射是對象的集合。為了實現它們基本的行為(規則),如果對象是不可變的,那么就需要使用兩個魔法方法,如果是可變的則需要使用4個。

__len__(self):這個方法應該返回集合中所含項目的數量。對于序列來說,這就是元素的個數。對于映射來說,則是鍵-值對的數量。

__getitem__(self,key):這個方法返回與所給鍵對應的值。對于一個序列,鍵應該是1個0~n-1的整數(或者像后面所說的負數),n是序列的長度;對于映射來說,可以使用任何種類的鍵。

__setitem__(self,key,value):這個方法應該按一定的方式存儲和key相關的value,該值隨后可使用__getitem__來獲取。當然,只能為可以修改的對象定義這個方法。

__delitem__(self,key):這個方法在對一部分對象使用del語句時被調用,同時必須刪除和元素相關的鍵。這個方法也是為可修改的對象定義的(并不是刪除全部的對象,而只刪除一些需要移除的元素)。

>>> def checkIndex(key):

...     if not isinstance(key,(int,long)):raise TypeError

...     if key<0:raise IndexError

...  

>>> class ArithmeticSequence:

...     def __init__(self,start=0,step=1):

...         self.start=start

...         self.step=step

...         self.changed={}

...     def __getitem__(self,key):

...         checkIndex(key)

...         try:return self.changed[key]

...         except KeyError:

...             return self.start+key*self.step

...     def __setitem__(self,key,value):

...         checkIndex(key)

...         self.changed[key]=value

...         

>>> s=ArithmeticSequence(1,2)

>>> s[4]

9

>>> s[4]=2

>>> s[4]

2

>>> s[5]

11

沒有實現__del__方法的原因是希望刪除元素是非法的:

>>> del s[4]

Traceback (most recent call last):

  File "<input>", line 1, in <module>

AttributeError: ArithmeticSequence instance has no attribute '__delitem__'

這個類沒有__len__方法,因為它是無限長的。

如果使用了一個非法類型的索引,就會引發TypeError異常,如果索引的類型是正確的但超出了范圍(在本例中為負數),則會引發IndexError異常:

>>> s[four]

Traceback (most recent call last):

  File "<input>", line 1, in <module>

NameError: name 'four' is not defined

>>> s[-4]

Traceback (most recent call last):

  File "<input>", line 1, in <module>

  File "<input>", line 7, in __getitem__

  File "<input>", line 3, in checkIndex

IndexError

子類化列表,字典和字符串

例子----帶有訪問計數的列表:

>>> class CounterList(list):

...     def __init__(self,*args):

...         super(CounterList,self).__init__(*args)

...         self.counter=0

...     def __getitem__(self,index):

...         self.counter +=1

...         return super(CounterList,self).__getitem__(index)

... 

CounterList類嚴重依賴于它的子類化超類(list)的行為CounterList類沒有重寫任何的方法(和append  extend, index一樣)都能被直接使用。在兩個被重寫的方法中,super方法被用來調用相應的超類的方法,只在__init__中添加了所需的初始化counter特性的行為,并在__getitem__中更新了counter特性。

>>> c1=CounterList(range(10))

>>> c1

[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]

>>> c1.reverse()

>>> c1

[9, 8, 7, 6, 5, 4, 3, 2, 1, 0]

>>> del c1[3:6]

>>> c1

[9, 8, 7, 3, 2, 1, 0]

>>> c1[4]+c1[2]

9

>>> c1.counter

2

CounterList在很多方面和列表的作用一樣,但它有一個counter特性(被初始化為0),每次列表元素被訪問時,它都會自增,所以在執行加法c1[4]+c1[2〕后,這個值自增兩次,變為2.


發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
主站蜘蛛池模板: 平武县| 泽库县| 西充县| 富蕴县| 荃湾区| 明溪县| 浏阳市| 徐州市| 什邡市| 米脂县| 和平区| 南澳县| 若尔盖县| 辽宁省| 宝清县| 安阳县| 志丹县| 石阡县| 汝阳县| 连城县| 屯门区| 平乡县| 古蔺县| 彝良县| 石楼县| 满城县| 奉新县| 鱼台县| 长汀县| 嘉禾县| 平乐县| 濮阳县| 永嘉县| 宜丰县| 大埔区| 临猗县| 保康县| 榆林市| 思茅市| 冕宁县| 游戏|