標籤:
1、單底線:開始的成員變數叫 保護變數(protected) 只有類對象和子類對象自己能訪問到這些變數
雙底線:開始的是 私人成員(private) 只有類對象自己能訪問,連子類對象也不能訪問
註:以單底線開頭(_foo)的代表不能直接存取的類屬性,需通過類提供的介面進行訪問,不能用“from xxx import *”而匯入;以雙底線開頭的(__foo)代表類的私人成員;以雙底線開頭和結尾的(__foo__)代表python裡特殊方法專用的標識,如 __init__()代表類的建構函式。
2、__slots__
正常情況下,定義一個class,建立一個class的執行個體後,可以給該執行個體綁定任何屬性和方法,這就是動態語言的靈活性
class Student(object):
pass
然後,嘗試給執行個體綁定一個屬性:
s=Student()
s.name=‘zhu‘
print s.name zhu
嘗試給執行個體綁定一個方法:
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
但是給一個執行個體綁定的方法,對另一個執行個體是不起作用的,為了給所有執行個體Binder 方法,可以給類classBinder 方法:
def set_score(self,score):
self.score=score
Student.set_score=MethodType(set_score,None,Student) 給類綁定一個方法
所以classBinder 方法後,所有執行個體都可以調用
s.set_score(100) 則s.score=100
s2=set_score(99) 則s2.score=99
思考:上面例子中,完全可以把set_score方法直接定義在class中,單動態綁定允許我們在程式啟動並執行過程中動態給class加上功能;這在靜態語言中很難實現
如果想要限制class的屬性,只允許Student執行個體添加name和age屬性???
為了達到限制的目的,Python允許在定義class的時候,定義一個特殊的__slots__變數,來限制class能添加的屬性
註:__slots__定義的屬性僅對當前類起作用,對繼承的子類時不起作用的;除非在子類中也定義__slots__,這樣,子類允許定義的屬性就是自身的__slots__加上父類的__slots__。
class Student(object):
__slots__=(‘name‘,‘age‘) 用tuple定義允許綁定屬性名稱
s=Student()
s.age=25
s.name=‘zhu‘
s.score=99 報AttributeError錯誤
3、@property:python內建的,負責把一個方法變成屬性調用
在綁定屬性時,我們直接把屬性暴露出去,雖然寫起來簡單,但是沒有檢查參數,導致成績隨便改
s=Student()
s.score=999
這顯然不和邏輯,為了限制score的範圍,通過set_score()方法設定成績,set_score()來擷取成績,這樣在set_score()方法中就可以檢查參數了:
使用@property
@property廣泛用在類的定義中,可以讓調用者寫出減短的代碼,同時保證對參數進行必要的檢查,這樣程式在運行時就減少了出錯的可能性
4、多重繼承;;Mixin的目的是給一個類增加多個功能;由於Python允許使用多重繼承,因此,Mixin就是一種常見的設計
5、定製類:python的class中還有許多這樣有特殊用途的函數,可以協助我們定製類
①__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)
若沒有__str__()函數則列印結果是:<__main__.Student object at 0x109afb190>
若直接敲變數s還是>>>s=Student(‘Micheal’)
>>>s 則<__main__.Student object at 0x109afb190>,這是因為直接顯示變數調用的不是__str__(),而是__repr__()
兩者區別:__str__() :返回使用者看到的字串
__repr__() :返回程式開發人員看到的字串,就是為調試用的
def __str__(self):... return ‘Student object (name: %s)‘ % self.name
__repr__=__str__
這樣直接單調用執行個體s時,>>>s 則Micheal
②__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...1123
物件導向進階編程