python 創建定製的序列

創建定製的序列

有很多方法讓你的Python類行爲可以像內置的序列(dict, tuple,list, string等等)。這是目前位置我最喜歡的魔術方法因爲它給你很搞的控制權限而且讓很多函數在你的類實例上工作的很出色。但是在開始之前,需要先講一些必須條件。

必須條件

現在我們開始講如何在Python中創建定製的序列,這個時候該講一講協議。協議(Protocols)與其他語言中的接口很相似。它給你很多你必須定義的方法。然而在Python中的協議是很不正式的,不需要明確聲明實現。事實上,他們更像一種指南。

我們爲什麼現在討論協議?因爲如果要定製容器類型的話需要用到這些協議。首先,實現不變容器的話有一個協議:實現不可變容器,你只能定義 __len____getitem__ (一會會講更多)。可變容器協議則需要所有不可變容器的所有另外還需要 __setitem__ __delitem__ 。最終,如果你希望你的對象是可迭代的話,你需要定義 __iter__ 會返回一個迭代器。迭代器必須遵循迭代器協議,需要有 __iter__ (返回它本身) 和 next

容器後的魔法

這些是容器使用的魔術方法。__len__(self)然會容器長度。對於可變不可變容器都需要有的協議的一部分。__getitem__(self, key)定義當一個條目被訪問時,使用符號 self[key] 。這也是不可變容器和可變容器都要有的協議的一部分。如果鍵的類型錯誤和 KeyError 或者沒有合適的值。那麼應該拋出適當的 TypeError 異常。__setitem__(self, key, value)定義當一個條目被賦值時的行爲,使用 self[key] = value 。這也是可變容器和不可變容器協議中都要有的一部分。__delitem__(self, key)定義當一個條目被刪除時的行爲(比如 del self[key])。這只是可變容器協議中的一部分。當使用一個無效的鍵時應該拋出適當的異常。__iter__(self)返回一個容器的迭代器。很多情況下會返回迭代器,尤其是當內置的 iter() 方法被調用的時候,或者當使用 for x in container 方式循環的時候。迭代器是他們本身的對象,他們必須定義返回 self__iter__ 方法。__reversed__(self)實現當 reversed() 被調用時的行爲。應該返回列表的反轉版本。__contains__(self, item)當調用 innot in 來測試成員是否存在時候 __contains__ 被定義。你問爲什麼這個不是序列協議的一部分?那是因爲當 __contains__ 沒有被定義的時候,Python會迭代這個序列並且當找到需要的值時會返回 True__concat__(self, other)最終,你可以通過 __concat__ 來定義當用其他的來連接兩個序列時候的行爲。當 + 操作符被調用時候會返回一個 selfother.__concat__ 被調用後的結果產生的新序列。

一個例子

在我們的例子中,讓我們看一看你可能在其他語言中 用到的函數構造語句的實現(比如 Haskell)。

class FunctionalList:
'''一個封裝了一些附加魔術方法比如 head, tail, init, last, drop, 和take的列表類。
'''

def __init__(self, values=None):
if values is None:
    self.values = []
else:
    self.values = values

def __len__(self):
    return len(self.values)

def __getitem__(self, key):
    #如果鍵的類型或者值無效,列表值將會拋出錯誤
    return self.values[key]

def __setitem__(self, key, value):
    self.values[key] = value

def __delitem__(self, key):
    del self.values[key]

def __iter__(self):
    return iter(self.values)

def __reversed__(self):
    return reversed(self.values)

def append(self, value):
    self.values.append(value)
def head(self):
    return self.values[0]
def tail(self):
    return self.values[1:]
def init(self):
    #返回一直到末尾的所有元素
    return self.values[:-1]
def last(self):
    #返回末尾元素
    return self.values[-1]
def drop(self, n):
    #返回除前n個外的所有元素
    return self.values[n:]
def take(self, n):
    #返回前n個元素
    return self.values[:n]


注:setitem只能設置已有條目,不能設置新條目

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章