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

首頁 > 編程 > Python > 正文

python魔法方法-自定義序列詳解

2019-11-25 16:38:09
字體:
來源:轉載
供稿:網友

自定義序列的相關魔法方法允許我們自己創建的類擁有序列的特性,讓其使用起來就像 python 的內置序列(dict,tuple,list,string等)。

如果要實現這個功能,就要遵循 python 的相關的協議。所謂的協議就是一些約定內容。例如,如果要將一個類要實現迭代,就必須實現兩個魔法方法:__iter__、next(python3.x中為__new__)。__iter__應該返回一個對象,這個對象必須實現 next 方法,通常返回的是 self 本身。而 next 方法必須在每次調用的時候都返回下一個元素,并且當元素用盡時觸發 StopIteration 異常。

而其實 for 循環的本質就是先調用對象的__iter__方法,再不斷重復調用__iter__方法返回的對象的 next 方法,觸發 StopIteration 異常時停止,并內部處理了這個異常,所以我們看不到異常的拋出。

這種關系就好像接口一樣,如果回顧以前幾篇的魔法方法,可以發現許多的內置函數得到的結果就是相應的魔法方法的返回值。

下面是一下相關的魔法方法:

•__len__(self)

•返回容器的長度。可變和不可變容器都要實現它,這是協議的一部分。

•__getitem__(self, key)

•定義當某一項被訪問時,使用self[key]所產生的行為。這也是可變容器和不可變容器協議的一部分。如果鍵的類型錯誤將產生TypeError;如果key沒有合適的值則產生KeyError。

•__setitem__(self, key, value)

•定義當一個條目被賦值時,使用self[key] = value所產生的行為。這也是可變容器協議的一部分。而且,在相應的情形下也會產生KeyError和TypeError。

•__delitem__(self, key)

•定義當某一項被刪除時所產生的行為。(例如del self[key])。這是可變容器協議的一部分。當你使用一個無效的鍵時必須拋出適當的異常。

•__iter__(self)

•返回一個容器迭代器,很多情況下會返回迭代器,尤其是當內置的iter()方法被調用的時候,以及當使用for x in container:方式循環的時候。迭代器是它們本身的對象,它們必須定義返回self的__iter__方法。

•__reversed__(self)

•實現當reversed()被調用時的行為。應該返回序列反轉后的版本。僅當序列是有序的時候實現它,例如列表或者元組。

•__contains__(self, item)

•定義了調用in和not in來測試成員是否存在的時候所產生的行為。這個不是協議要求的內容,但是你可以根據自己的要求實現它。當__contains__沒有被定義的時候,Python會迭代這個序列,并且當找到需要的值時會返回True。

•__missing__(self, key)

•其在dict的子類中被使用。它定義了當一個不存在字典中的鍵被訪問時所產生的行為。(例如,如果我有一個字典d,當"george"不是字典中的key時,使用了d["george"],此時d.__missing__("george")將會被調用)。

下面是一個代碼示例:

class Foo(object):  def __init__(self, key, value):    self.key = []    self.value = []    self.key.append(key)    self.value.append(value)  def __len__(self):    return len(self.key)  def __getitem__(self, item):    try:      __index = self.key.index(item)      return self.value[__index]    except ValueError:      raise KeyError('can not find the key')  def __setitem__(self, key, value):    if key not in self.key:      self.key.append(key)      self.value.append(value)    else:      __index = self.key.index(key)      self.value[__index] = value  def __delitem__(self, key):    try:      __index = self.key.index(key)      del self.key[__index]      del self.value[__index]    except ValueError:      raise KeyError('can not find the key')  def __str__(self):    result_list = []    for index in xrange(len(self.key)):      __key = self.key[index]      __value = self.value[index]      result = __key, __value      result_list.append(result)    return str(result_list)  def __iter__(self):    self.__index = 0    return self  def next(self):    if self.__index == len(self.key):      self.__index = 0      raise StopIteration()    else:      __key = self.key[self.__index]      __value = self.value[self.__index]      result = __key, __value      self.__index += 1      return result  def __reversed__(self):    __result = self.value[:]    __result.reverse()    return __result  def __contains__(self, item):    if item in self.value:      return True    else:      return False

這里創建一個模擬字典的類,這個類的內部維護了兩個列表,key 負責儲存鍵,value 負責儲存值,兩個列表通過索引的一一對應,從而達到模擬字典的目的。

首先,我們看看__len__方法,按照協議,這個方法應該返回容器的長度,因為這個類在設計的時候要求兩個列表必須等長,所以理論上返回哪個列表的長度都是一樣的,這里我選擇返回 key 的長度。

然后是__getitem__方法。這個方法會在a['scolia']時,調用a.__getitem__('scolia')。也就是說這個方法定義了元素的獲取,我這里的思路是先找到 key 列表中建的索引,然后用索引去 value 列表中找對應的元素,然后將其返回。然后為了進一步偽裝成字典,我捕獲了可能產生的 ValueError (這是 item 不在 key 列表中時觸發的異常),并將其偽裝成字典找不到鍵時的 KeyError。

理論上只要實現了上面兩個方法,就可以得到一個不可變的容器了。但是我覺得并不滿意所以繼續拓展。

__setitem__(self, key, value)方法定義了 a['scolia'] = 'good' 這種操作時的行為,此時將會調用a.__setitem__('scolia', 'good') 因為是綁定方法,所以self是自動傳遞的,我們不用理。這里我也模擬了字典中對同一個鍵賦值時會造成覆蓋的特性。這個方法不用返回任何值,所以return語句也省略了。

__delitem__(self, key)方法定義了del a['scolia'] 這類操作時候的行為,里面的‘scolia'就作為參數傳進去。這里也進行了異常的轉換。

只有實現里以上四個方法,就可以當做可變容器來使用了。有同學可能發現并沒有切片對應的魔法方法,而事實上,我也暫時沒有找到先,這部分內容先擱著一邊。

接下來的 __str__ 是對應于 str() 函數,在類的表示中會繼續討論,這里是為了 print 語句好看才加進去的,因為print語句默認就是調用str()函數。

__iter__和next方法在開頭的時候討論過了,這里是為了能讓其進行迭代操作而加入的。

__reversed__(self)方法返回一個倒序后的副本,這里體現了有序性,當然是否需要還是要看個人。

__contains__實現了成員判斷,這里我們更關心value列表中的數據,所以判斷的是value列表。該方法要求返回布爾值。

下面是相應的測試:

a = Foo('scolia', 'good')a[123] = 321a[456] = 654a[789] = 987print adel a[789]print afor x, y in a:  print x, yprint reversed(a)print 123 in aprint 321 in a

•__missing__(self, key)

class Boo(dict):  def __new__(cls, *args, **kwargs):    return super(Boo, cls).__new__(cls)  def __missing__(self, key):    return 'The key(%s) can not be find.'% key

測試:

b = Boo()b['scolia'] = 'good'print b['scolia']print b['123']

 

當然你也可以在找不到 key 的時候觸發異常,具體實現看個人需求。

以上這篇python魔法方法-自定義序列詳解就是小編分享給大家的全部內容了,希望能給大家一個參考,也希望大家多多支持武林網。

發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
主站蜘蛛池模板: 隆尧县| 乌鲁木齐市| 息烽县| 沈丘县| 阳曲县| 肇源县| 河东区| 麻阳| 迭部县| 土默特右旗| 莲花县| 台中县| 渑池县| 廉江市| 营山县| 九龙坡区| 婺源县| 米泉市| 江北区| 阜南县| 城口县| 邓州市| 新津县| 清原| 蕉岭县| 隆回县| 汉川市| 普定县| 科尔| 仙居县| 漳浦县| 吉隆县| 光山县| 吴忠市| 扶余县| 安新县| 略阳县| 青田县| 云浮市| 黑山县| 博客|