再一次重新學習Python——面向物件高階程式設計
給例項繫結一個方法:
>>> def set_age(self, age): # 定義一個函式作為例項方法
... self.age = age
...
>>> from types import MethodType
>>> s.set_age = MethodType(set_age, s, Student) # 給例項繫結一個方法
>>> s.set_age(25) # 呼叫例項方法
>>> s.age # 測試結果
25
為了給所有例項都繫結方法,可以給class繫結方法:
>>> def set_score(self, score): ... self.score = score ... >>> Student.set_score = MethodType(set_score, None, Student)
-
使用__slots__
用來限制class可以新增的屬性
>>> class Student(object):
... __slots__ = ('name', 'age') # 用tuple定義允許繫結的屬性名稱
...
使用__slots__要注意,它定義的屬性只對當前類起作用,對繼承的子類是不起作用的。
除非在子類中也定義__slots__,這樣,子類允許定義的屬性就是自身的__slots__加上父類的__slots__。
-
使用@property
Python內建的@property裝飾器負責把一個方法變成屬性呼叫。
class Student(object): @property def score(self): return self._score @score.setter def score(self, value): if not isinstance(value, int): raise ValueError('score must be an integer!') if value < 0 or value > 100: raise ValueError('score must between 0 ~ 100!') self._score = value ''' @property def birth(self): return self._birth @birth.setter def birth(self, value): self._birth = value '''
@property
的實現比較複雜,我們先考察如何使用。把一個getter方法變成屬性,只需要加上@property
就可以了,此時,@property
本身又建立了另一個裝飾器@score.setter
,負責把一個setter方法變成屬性賦值,於是,我們就擁有一個可控的屬性操作:
>>> s = Student() >>> s.score = 60 # OK,實際轉化為s.set_score(60) >>> s.score # OK,實際轉化為s.get_score() 60 >>> s.score = 9999 Traceback (most recent call last): ... ValueError: score must between 0 ~ 100!
-
多重繼承
多重繼承就是繼承多個父類,這樣一個子類就可以同時獲得多個父類的所有功能。
例如
class Dog(Mammal, Runnable):
pass
Mixin模式
目的是給一個類增加多個功能,在設計類的時候,優先考慮通過多重繼承來組合多個Mixin的功能。
__str__()返回一個好看的字串————改變的是print輸出變數
__repr__()改變的事直接顯示變數呼叫,為除錯服務
__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 # 返回下一個值
現在,試試把Fib例項作用於for迴圈:
>>> for n in Fib():
... print n
...
1
1
2
3
5
...
46368
75025
更多定製類翻看部落格
-
使用元類
type()和metaclass(元類)
先定義metaclass,就可以建立類,最後建立例項。metaclass允許你建立類或者修改類。換句話說,你可以把類看成是metaclass創建出來的“例項”。