自訂序列的相關魔法方法允許我們自己創建的類別擁有序列的特性,讓其使用起來就像 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] = 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
•__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魔法方法-自定义序列详解就是小编分享给大家的全部内容了,希望能给大家一个参考,也希望大家多多支持脚本之家。

Python适合数据科学、Web开发和自动化任务,而C 适用于系统编程、游戏开发和嵌入式系统。Python以简洁和强大的生态系统著称,C 则以高性能和底层控制能力闻名。

2小時內可以學會Python的基本編程概念和技能。 1.學習變量和數據類型,2.掌握控制流(條件語句和循環),3.理解函數的定義和使用,4.通過簡單示例和代碼片段快速上手Python編程。

Python在web開發、數據科學、機器學習、自動化和腳本編寫等領域有廣泛應用。 1)在web開發中,Django和Flask框架簡化了開發過程。 2)數據科學和機器學習領域,NumPy、Pandas、Scikit-learn和TensorFlow庫提供了強大支持。 3)自動化和腳本編寫方面,Python適用於自動化測試和系統管理等任務。

兩小時內可以學到Python的基礎知識。 1.學習變量和數據類型,2.掌握控制結構如if語句和循環,3.了解函數的定義和使用。這些將幫助你開始編寫簡單的Python程序。

如何在10小時內教計算機小白編程基礎?如果你只有10個小時來教計算機小白一些編程知識,你會選擇教些什麼�...

使用FiddlerEverywhere進行中間人讀取時如何避免被檢測到當你使用FiddlerEverywhere...

Python3.6環境下加載Pickle文件報錯:ModuleNotFoundError:Nomodulenamed...

如何解決jieba分詞在景區評論分析中的問題?當我們在進行景區評論分析時,往往會使用jieba分詞工具來處理文�...


熱AI工具

Undresser.AI Undress
人工智慧驅動的應用程序,用於創建逼真的裸體照片

AI Clothes Remover
用於從照片中去除衣服的線上人工智慧工具。

Undress AI Tool
免費脫衣圖片

Clothoff.io
AI脫衣器

AI Hentai Generator
免費產生 AI 無盡。

熱門文章

熱工具

EditPlus 中文破解版
體積小,語法高亮,不支援程式碼提示功能

記事本++7.3.1
好用且免費的程式碼編輯器

SecLists
SecLists是最終安全測試人員的伙伴。它是一個包含各種類型清單的集合,這些清單在安全評估過程中經常使用,而且都在一個地方。 SecLists透過方便地提供安全測試人員可能需要的所有列表,幫助提高安全測試的效率和生產力。清單類型包括使用者名稱、密碼、URL、模糊測試有效載荷、敏感資料模式、Web shell等等。測試人員只需將此儲存庫拉到新的測試機上,他就可以存取所需的每種類型的清單。

MinGW - Minimalist GNU for Windows
這個專案正在遷移到osdn.net/projects/mingw的過程中,你可以繼續在那裡關注我們。 MinGW:GNU編譯器集合(GCC)的本機Windows移植版本,可自由分發的導入函式庫和用於建置本機Windows應用程式的頭檔;包括對MSVC執行時間的擴展,以支援C99功能。 MinGW的所有軟體都可以在64位元Windows平台上運作。

ZendStudio 13.5.1 Mac
強大的PHP整合開發環境