__str__
這是因為直接顯示變量調用的不是__str__(),而是__repr__(),兩者的區別是__str__()返回用戶看到的字符串,而__repr__()返回程序開發者看到的字符串,也就是說,__repr__()是為調試服務的。
解決辦法是再定義一個__repr__()。但是通常__str__()和__repr__()代碼都是一樣的,所以,有個偷懶的寫法
定義后加一段
__repr__ = __str__
如果一個類想被用于for ... in循環,類似list或tuple那樣,就必須實現一個__iter__()方法,該方法返回一個迭代對象
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 # 返回下一個值
__getitem__
要表現得像list那樣按照下標取出元素,需要實現__getitem__()方法:
class Fib(object):
? ? def __getitem__(self, n):
? ? ? ? a, b = 1, 1
? ? ? ? for x in range(n):
? ? ? ? ? ?a, b = b, a + b
? ? ? ? return a
對于Fib卻報錯。原因是__getitem__()傳入的參數可能是一個int,也可能是一個切片對象slice,所以要做判斷
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
__getattr__
寫一個__getattr__()方法,動態返回一個屬性
def __getattr__(self, attr):
? ? if attr=='score':
? ? ? ? return 99
__call__
任何類,只需要定義一個__call__()方法,就可以直接對實例進行調用
class Student(object):
? ? def __init__(self, name):
? ? ? ?self.name = name
? ? def __call__(self):
? ? ? ? print('My name is %s.' % self.name)
能被調用的對象就是一個Callable對象
>>> callable(Student())
True