python 面向對象九 定制類
一、定制類,實質就是我們自己重寫特殊函數
看到類似__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) ... 1 1 2 3 5 ... 46368 75025
六、__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 面向對象九 定制類