面向對象
高級
-
動態添加屬性
-
python可以動態爲對象綁定屬性,但是不會影響到同類的其他對象。
class Person: pass p1=Person() p2=Person() p1.gender='male' print(p1.gender) print(p2.gender) #'Person' object has no attribute 'gender'
-
動態爲對象綁定方法
from types import MethodType class Person: pass def displayMe(self): print('my genderis:', self.gender) # 給一個實例綁定的方法,對另一個實例是不起作用的: p1.dispalyMe=MethodType(displayMe,p1) p1.dispalyMe()
-
通過動態給類增加屬性和方法,可以實現所有對象都增加了屬性和方法
Person.gender='male' def displayMe(self): print('my genderis:', self.gender) Person.displayMe=displayMe
-
使用__slots__限制實例的屬性.比如,只允許對Student實例添加name和age屬性。
-
class Person(object): __slots__=('name','age') p1=Person() print(dir(p1)) # 這是看到p1對象裏已經存在name和age屬性了 try: p1.gender = 'female' except Exception: print('使用__slots__限制實例的屬性')
-
-
刪除屬性
class Person: def __init__(self): self.age=1 p1=Person() p2=Person() p1.gender='male' Person.nation='china' del p1.gender del p1.nation #error nation屬於類的,不可以通過對象刪除 del Person.nation del p1.age #這是可以的
類屬性也可以通過del動態刪除
-
利用函數動態綁定
#該語句只能添加屬性,不能添加方法 setattr(ee2, 'age', 8) # 添加屬性 'age' 值爲 8 getattr(ee1, 'age') # 返回 'age' 屬性的值 hasattr(ee1, 'age') # 如果存在 'age' 屬性返回 True。 delattr(ee1, 'age') # 刪除屬性 'age'
-
私有屬性
1、 _xx 以單下劃線開頭的表示的是protected類型的變量。同一個包內可以訪問(即爲同一個作用域),即保護類型只能允許其本身與子類進行訪問。若內部變量標示,如: 當使用“from M import”時,不會將以一個下劃線開頭的對象引入 。
2、 __xx 雙下劃線的表示的是私有類型的變量。只能允許這個類本身進行訪問了,連子類也不可以用於命名一個類屬性(類變量),調用時名字被改變(在類FooBar內部,__boo變成_FooBar__boo,如self._FooBar__boo)
3、 __xx__定義的是特列方法。用戶控制的命名空間內的變量或是屬性,如init , __import__或是file 。只有當文檔有說明時使用,不要自己定義這類變量。 (就是說這些是python內部定義的變量名)
python默認的成員函數和成員變量都是公開的,沒有像其他類似語言的public,private等關鍵字修飾.但是可以在變量前面加上兩個下劃線"",這樣的話函數或變量就變成私有的.這是python的私有變量軋壓(這個翻譯好拗口),英文是(private name mangling.) **情況就是當變量被標記爲私有後,在變量的前端插入類名,再類名前添加一個下劃線"",即形成了_ClassName__變量名.
class pub(): # protected類型的變量和方法 在類的實例中可以獲取和調用 _name = 'protected類型的變量' __info = '私有類型的變量' def _func(self): print("這是一個protected類型的方法") def __func2(self): print('這是一個私有類型的方法') # 如果想要在實例中獲取到類的私有類形變量可以通過在類中聲明普通方法,返回私有類形變量的方式獲取 def get(self): return(self.__info) p=pub() p.__info # error 因爲__info是私有變量只有在類內部纔可見,所以要用內部方法
複習:
Python內置類屬性
__dict__ : 類的屬性(包含一個字典,由類的數據屬性組成) __doc__ :類的文檔字符串 __module__: 類定義所在的模塊(類的全名是'__main__.className',如果類位於一個導入模塊mymod中,那麼className.__module__ 等於 mymod) __bases__ : 類的所有父類構成元素(包含了一個由所有父類組成的元組)
-
只讀屬性
@ property 作用就是採用訪問屬性的方式訪問函數。
class Car: __wheels=4 @property def wheels(self): return self.__wheels
@property可以把方法變爲屬性,
class Car: __wheels=4 __voice='didi' def __init__(self,color): self.color=color self.speed=80 @property def run(self): print('i can run %d speed'%self.speed) @run.setter def run(self,wh): self.speed=wh car1=Car('blue') print(car1.color) car1.run=120 car1.run
這個屬性是不可以通過del car1.run 來刪除的。因爲他本來就不是一個屬性
@run.deleter def run(self): del self.speed print("你的車輪已經被拆除...")
-
靜態方法
普通的方法,可以在實例化後直接調用,並且在方法裏可以通過self.調用實例變量或類變量,但靜態方法是不可以訪問實例變量或類變量的,一個不能訪問實例變量和類變量的方法,其實相當於跟類本身已經沒什麼關係了,它與類唯一的關聯就是需要通過類名來調用這個方法。
class Car: __wheels=4 __voice='didi' def __init__(self,color): self.color=color @property def wheels(self): return self.__wheels #靜態方法在類中也不需要傳入 self參數 @staticmethod def wash(): print('i am washing')
-
類方法
通過@classmethod裝飾器實現,類方法和普通方法的區別是, 類方法只能訪問類變量,不能訪問實例變量
class Car: __wheels=4 __voice='didi' def __init__(self,color): self.color=color @property def wheels(self): return self.__wheels @classmethod def dudu(cls): print(cls.__voice) @staticmethod def wash(): print('i am washing')
- 類方法節省空間,但是不能訪問屬性
#析構函數一般放手動回收的資源
#爲什麼判斷一個析構函數是否屬於一個類:
#繼承先調用後邊初始化的,多重繼承(B,C),先調用C
#繼承過程中儘量不要進行屬性的擴展
#寫功能接口,不能將所有功能放於一個類當中,以免多重繼承出現交叉問題
#多重繼承時(一個類有兩個屬性,一個類有三個屬性,繼承之後初始化會出現錯誤
#通過接口來改變上述交叉問題
#對象方法是用來進行測試的:display