標籤:計數 none 注意 mic code step key 錯誤 集合
一、定製類,實質就是我們自己重寫特殊函數
看到類似__slots__這種形如__xxx__的變數或者函數名就要注意,這些在Python中是有特殊用途的。
__slots__我們已經知道怎麼用了,__len__()方法我們也知道是為了能讓class作用於len()函數。
除此之外,Python的class中還有許多這樣有特殊用途的函數,可以協助我們定製類。
二、__len__()方法
>>> class MyStr(str): def __init__(self, s): self.__s = s def __len__(self): return len(self.__s) - 1 >>> s = MyStr(‘abc‘)>>> len(s)2
三、__str__()方法
>>> class Student(object):... def __init__(self, name):... self.name = name... def __str__(self):... return ‘Student object (name: %s)‘ % self.name...>>> print(Student(‘Michael‘))Student object (name: Michael)
四、__repr__()方法
>>> s = Student(‘Michael‘)>>> s<__main__.Student object at 0x109afb310>
這是因為直接顯示變數調用的不是__str__(),而是__repr__(),兩者的區別是__str__()返回使用者看到的字串,而__repr__()返回程式開發人員看到的字串,也就是說,__repr__()是為調試服務的。
解決辦法是再定義一個__repr__()。但是通常__str__()和__repr__()代碼都是一樣的,所以,有個偷懶的寫法:
class Student(object): def __init__(self, name): self.name = name def __str__(self): return ‘Student object (name=%s)‘ % self.name __repr__ = __str__
五、__iter__()方法
如果一個類想被用於for ... in迴圈,類似list或tuple那樣,就必須實現一個__iter__()方法,該方法返回一個迭代對象,然後,Python的for迴圈就會不斷調用該迭代對象的__next__()方法拿到迴圈的下一個值,直到遇到StopIteration錯誤時退出迴圈。
我們以斐波那契數列為例,寫一個Fib類,可以作用於for迴圈:
class Fib(object): def __init__(self): self.a, self.b = 0, 1 # 初始化兩個計數器a,b def __iter__(self): return self # 執行個體本身就是迭代對象,故返回自己 def __next__(self): self.a, self.b = self.b, self.a + self.b # 計算下一個值 if self.a > 100000: # 退出迴圈的條件 raise StopIteration() return self.a # 返回下一個值
>>> for n in Fib():... print(n)...11235...4636875025
六、__getitem__()方法
class Fib(object): def __getitem__(self, n): if isinstance(n, int): # n是索引 a, b = 1, 1 for x in range(n): a, b = b, a + b return a if isinstance(n, slice): # n是切片 start = n.start stop = n.stop if start is None: start = 0 a, b = 1, 1 L = [] for x in range(stop): if x >= start: L.append(a) a, b = b, a + b return L
但是沒有對step參數作處理,
也沒有對負數作處理,所以,要正確實現一個__getitem__()還是有很多工作要做的。
此外,如果把對象看成dict,__getitem__()的參數也可能是一個可以作key的object,例如str。
與之對應的是__setitem__()方法,把對象視作list或dict來對集合賦值。最後,還有一個__delitem__()方法,用於刪除某個元素。
總之,通過上面的方法,我們自己定義的類表現得和Python內建的list、tuple、dict沒什麼區別,這完全歸功於動態語言的“鴨子類型”,不需要強制繼承某個介面。
python 物件導向九 定製類