亚洲免费在线-亚洲免费在线播放-亚洲免费在线观看-亚洲免费在线观看视频-亚洲免费在线看-亚洲免费在线视频

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

系統(tǒng) 1843 0

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

如果要實(shí)現(xiàn)這個(gè)功能,就要遵循 python 的相關(guān)的協(xié)議。所謂的協(xié)議就是一些約定內(nèi)容。例如,如果要將一個(gè)類要實(shí)現(xiàn)迭代,就必須實(shí)現(xiàn)兩個(gè)魔法方法:__iter__、next(python3.x中為_(kāi)_new__)。__iter__應(yīng)該返回一個(gè)對(duì)象,這個(gè)對(duì)象必須實(shí)現(xiàn) next 方法,通常返回的是 self 本身。而 next 方法必須在每次調(diào)用的時(shí)候都返回下一個(gè)元素,并且當(dāng)元素用盡時(shí)觸發(fā) StopIteration 異常。

而其實(shí) for 循環(huán)的本質(zhì)就是先調(diào)用對(duì)象的__iter__方法,再不斷重復(fù)調(diào)用__iter__方法返回的對(duì)象的 next 方法,觸發(fā) StopIteration 異常時(shí)停止,并內(nèi)部處理了這個(gè)異常,所以我們看不到異常的拋出。

這種關(guān)系就好像接口一樣,如果回顧以前幾篇的魔法方法,可以發(fā)現(xiàn)許多的內(nèi)置函數(shù)得到的結(jié)果就是相應(yīng)的魔法方法的返回值。

下面是一下相關(guān)的魔法方法:

?__len__(self)

?返回容器的長(zhǎng)度。可變和不可變?nèi)萜鞫家獙?shí)現(xiàn)它,這是協(xié)議的一部分。

?__getitem__(self, key)

?定義當(dāng)某一項(xiàng)被訪問(wèn)時(shí),使用self[key]所產(chǎn)生的行為。這也是可變?nèi)萜骱筒豢勺內(nèi)萜鲄f(xié)議的一部分。如果鍵的類型錯(cuò)誤將產(chǎn)生TypeError;如果key沒(méi)有合適的值則產(chǎn)生KeyError。

?__setitem__(self, key, value)

?定義當(dāng)一個(gè)條目被賦值時(shí),使用self[key] = value所產(chǎn)生的行為。這也是可變?nèi)萜鲄f(xié)議的一部分。而且,在相應(yīng)的情形下也會(huì)產(chǎn)生KeyError和TypeError。

?__delitem__(self, key)

?定義當(dāng)某一項(xiàng)被刪除時(shí)所產(chǎn)生的行為。(例如del self[key])。這是可變?nèi)萜鲄f(xié)議的一部分。當(dāng)你使用一個(gè)無(wú)效的鍵時(shí)必須拋出適當(dāng)?shù)漠惓!?

?__iter__(self)

?返回一個(gè)容器迭代器,很多情況下會(huì)返回迭代器,尤其是當(dāng)內(nèi)置的iter()方法被調(diào)用的時(shí)候,以及當(dāng)使用for x in container:方式循環(huán)的時(shí)候。迭代器是它們本身的對(duì)象,它們必須定義返回self的__iter__方法。

?__reversed__(self)

?實(shí)現(xiàn)當(dāng)reversed()被調(diào)用時(shí)的行為。應(yīng)該返回序列反轉(zhuǎn)后的版本。僅當(dāng)序列是有序的時(shí)候?qū)崿F(xiàn)它,例如列表或者元組。

?__contains__(self, item)

?定義了調(diào)用in和not in來(lái)測(cè)試成員是否存在的時(shí)候所產(chǎn)生的行為。這個(gè)不是協(xié)議要求的內(nèi)容,但是你可以根據(jù)自己的要求實(shí)現(xiàn)它。當(dāng)__contains__沒(méi)有被定義的時(shí)候,Python會(huì)迭代這個(gè)序列,并且當(dāng)找到需要的值時(shí)會(huì)返回True。

?__missing__(self, key)

?其在dict的子類中被使用。它定義了當(dāng)一個(gè)不存在字典中的鍵被訪問(wèn)時(shí)所產(chǎn)生的行為。(例如,如果我有一個(gè)字典d,當(dāng)"george"不是字典中的key時(shí),使用了d["george"],此時(shí)d.__missing__("george")將會(huì)被調(diào)用)。

下面是一個(gè)代碼示例:

            
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
          

這里創(chuàng)建一個(gè)模擬字典的類,這個(gè)類的內(nèi)部維護(hù)了兩個(gè)列表,key 負(fù)責(zé)儲(chǔ)存鍵,value 負(fù)責(zé)儲(chǔ)存值,兩個(gè)列表通過(guò)索引的一一對(duì)應(yīng),從而達(dá)到模擬字典的目的。

首先,我們看看__len__方法,按照協(xié)議,這個(gè)方法應(yīng)該返回容器的長(zhǎng)度,因?yàn)檫@個(gè)類在設(shè)計(jì)的時(shí)候要求兩個(gè)列表必須等長(zhǎng),所以理論上返回哪個(gè)列表的長(zhǎng)度都是一樣的,這里我選擇返回 key 的長(zhǎng)度。

然后是__getitem__方法。這個(gè)方法會(huì)在a['scolia']時(shí),調(diào)用a.__getitem__('scolia')。也就是說(shuō)這個(gè)方法定義了元素的獲取,我這里的思路是先找到 key 列表中建的索引,然后用索引去 value 列表中找對(duì)應(yīng)的元素,然后將其返回。然后為了進(jìn)一步偽裝成字典,我捕獲了可能產(chǎn)生的 ValueError (這是 item 不在 key 列表中時(shí)觸發(fā)的異常),并將其偽裝成字典找不到鍵時(shí)的 KeyError。

理論上只要實(shí)現(xiàn)了上面兩個(gè)方法,就可以得到一個(gè)不可變的容器了。但是我覺(jué)得并不滿意所以繼續(xù)拓展。

__setitem__(self, key, value)方法定義了 a['scolia'] = 'good' 這種操作時(shí)的行為,此時(shí)將會(huì)調(diào)用a.__setitem__('scolia', 'good') 因?yàn)槭墙壎ǚ椒ǎ詓elf是自動(dòng)傳遞的,我們不用理。這里我也模擬了字典中對(duì)同一個(gè)鍵賦值時(shí)會(huì)造成覆蓋的特性。這個(gè)方法不用返回任何值,所以return語(yǔ)句也省略了。

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

只有實(shí)現(xiàn)里以上四個(gè)方法,就可以當(dāng)做可變?nèi)萜鱽?lái)使用了。有同學(xué)可能發(fā)現(xiàn)并沒(méi)有切片對(duì)應(yīng)的魔法方法,而事實(shí)上,我也暫時(shí)沒(méi)有找到先,這部分內(nèi)容先擱著一邊。

接下來(lái)的 __str__ 是對(duì)應(yīng)于 str() 函數(shù),在類的表示中會(huì)繼續(xù)討論,這里是為了 print 語(yǔ)句好看才加進(jìn)去的,因?yàn)閜rint語(yǔ)句默認(rèn)就是調(diào)用str()函數(shù)。

__iter__和next方法在開(kāi)頭的時(shí)候討論過(guò)了,這里是為了能讓其進(jìn)行迭代操作而加入的。

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

__contains__實(shí)現(xiàn)了成員判斷,這里我們更關(guān)心value列表中的數(shù)據(jù),所以判斷的是value列表。該方法要求返回布爾值。

下面是相應(yīng)的測(cè)試:

            
a = Foo('scolia', 'good')
a[123] = 321
a[456] = 654
a[789] = 987
print a
del a[789]
print a
for x, y in a:
  print x, y
print reversed(a)
print 123 in a
print 321 in a
          

python魔法方法-自定義序列詳解_第1張圖片

?__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
          

測(cè)試:

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

?

當(dāng)然你也可以在找不到 key 的時(shí)候觸發(fā)異常,具體實(shí)現(xiàn)看個(gè)人需求。

以上這篇python魔法方法-自定義序列詳解就是小編分享給大家的全部?jī)?nèi)容了,希望能給大家一個(gè)參考,也希望大家多多支持腳本之家。


更多文章、技術(shù)交流、商務(wù)合作、聯(lián)系博主

微信掃碼或搜索:z360901061

微信掃一掃加我為好友

QQ號(hào)聯(lián)系: 360901061

您的支持是博主寫(xiě)作最大的動(dòng)力,如果您喜歡我的文章,感覺(jué)我的文章對(duì)您有幫助,請(qǐng)用微信掃描下面二維碼支持博主2元、5元、10元、20元等您想捐的金額吧,狠狠點(diǎn)擊下面給點(diǎn)支持吧,站長(zhǎng)非常感激您!手機(jī)微信長(zhǎng)按不能支付解決辦法:請(qǐng)將微信支付二維碼保存到相冊(cè),切換到微信,然后點(diǎn)擊微信右上角掃一掃功能,選擇支付二維碼完成支付。

【本文對(duì)您有幫助就好】

您的支持是博主寫(xiě)作最大的動(dòng)力,如果您喜歡我的文章,感覺(jué)我的文章對(duì)您有幫助,請(qǐng)用微信掃描上面二維碼支持博主2元、5元、10元、自定義金額等您想捐的金額吧,站長(zhǎng)會(huì)非常 感謝您的哦!!!

發(fā)表我的評(píng)論
最新評(píng)論 總共0條評(píng)論
主站蜘蛛池模板: 欧美毛片在线播放观看 | 看福利影院 | jizzjizz中国丝袜美女 | 久久国产香蕉视频 | 成人在线视频网站 | 亚洲视频精品 | 日本在线毛片视频免费看 | 伦理不卡 | 91成人免费福利网站在线 | 国产美女网址 | 尹人香蕉久久99天天 | 天天做天天做天天综合网 | 亚洲永久精品ww47 | 国产精品国产高清国产专区 | 99久热在线精品视频观看 | 成人国产精品免费视频 | 91精品全国免费观看老司机 | 九九色综合 | 综合另类 | 日本高清毛片视频在线看 | 高清视频在线播放 | 国产福利一区二区在线观看 | 天天色天天干天天射 | 亚洲欧美另类国产 | 久久国产精品-久久精品 | 日韩精品第三页 | 在线xxxx| 精品国偷自产在线 | 国产极品精频在线观看 | 不卡网站 | 国产精品看片 | m3u8久久国产精品影院 | 成人影院一区二区三区 | 国产精品乱码免费一区二区 | 久久成人综合 | 日韩国产中文字幕 | 日本网站在线 | 高清国产精品久久久久 | 国产精品福利一区二区久久 | 精品精品国产欧美在线观看 | 国产成人精品永久免费视频 |