類與實例
class Student(object): # class 類名(繼承)
pass
- init()方法就是java中的構造器
- 類中的self相當於java中的this,java不用顯示聲明,python中需要在參數列表中聲明
訪問限制
- 私有屬性用雙下劃線__開頭,只有內部可訪問 (private)
- 訪問需要類提供get方法,這和java一樣
_ 修改就需要set方法 - 實際上,並不是私有的,只是python解釋器給屬性改了一個名,變為
._類名__屬性名
- python中雙下劃線開頭與結尾的,都是特殊變量,一般不能用
- 發現個好玩的,即使類中沒有的屬性,也是可以xx.xx = xx進行設置的,然後就可以使用了
繼承
- 繼承會引發多態
- 子類是父類,父類不是子類
- 調用方只管調用,不管細節,無需知道子類型,從而盡可能滿足開閉原則
- java是靜態語言,它在進行編譯的時候就要來檢查傳入對象的類型是否合法
- Python是動態語言,不需要保證類型完全,只需要它有本方法中需要的方法和屬性就ok了
- 鴨子類型,無需嚴格繼承,只要 看起來像鴨子,走起來也像鴨子 就ok
對象信息
- type(obj) 類型,指向函數
- type(obj)
if type(xxx) == type(已知類型)
if type(xxx) == types.FunctionType
判斷是否是函數…
- instance(obj,已知類型) 判斷類型是否相等
- 返回True or False
- 可用於繼承
- 判斷是否是其中一種 instance(obj,(xxx,xxx))
- dir(obj) 將所有方法 屬性 字符串列表返回
- len(obj) 獲取對象的長度
- hasattr(obj,“xxx”) 是否擁有某種屬性
- getattr(obj,“xxx”,404) 最後一個參數是默認值,防止不存在報錯
- setattr(obj,“xxx”,xx)
- 結合上面的鴨子類型,可以使用對象信息來判斷是否像鴨子
實例屬性與類屬性
- 實例可以任意綁定屬性
- 類沒有定義name屬性,但我可以 實例.name=xxx,然後用
slots
- 作為動態語言,python可以給實例綁定方法與屬性
- 而給類動態的綁定,則可以對每個實例都適用,具體操作和實例的綁定一樣
- 為了限制綁定,需要
__slots__
- 其作為一個變量,可以定義 允許綁定的 屬性名稱
- 其他屬性是不能夠綁定的
- 對繼承的子類無效
@property
- 一般的屬性都是不對外暴露的,所以需要getter方法,setter方法
- 所以實際上可以使用 @property 來讓get方法變成屬性,然後使用 @屬性.setter 注解setter方法
class Stu(Object):
@property
def score(self): # 該注解下就是屬性名稱
return self.__score
@score.setter
def score(self,val):
self.__score = val
- 此時就可以直接 xx.屬性 進行賦值與調用,不用寫get賦值了,方便很多
xx = Stu()
xx.score = css
print(xx.score)
- 原理是裝飾器
- 注意 屬性的方法名不要與 實際的屬性名 相同
- 如果相同,會發生 自環,從而導致無限遞歸,最終棧溢出
- 注意這裡的無論啥方法,名稱都要統一,也就是你 注解定義了score,那麼所有的方法也得叫score
多重繼承
- 多個類別交叉時,就會造成 類的層次復雜
- 這點區別於java,java是單繼承,然後使用接口來進行擴展
class Bat(Mammal,FlyableMixIn,XxxMinIn):
pass
- 同時繼承多個父類的功能
- 我們可以把繼承的第一個類叫做主線,其他額外混入的類,稱為MixIn
定制類
- str() 打印實例信息,直接print即可,可自定義
- repr() 打印實例信息,為調試服務
- iter() 實現該方法,返回一個迭代對象,該類可用於 for…in,變成一個Iterable對象
- getitem()可以將類當成list來使用,按下邊訪問元素
- getattr()當有屬性找不到時,python解釋器就會調用該方法
- call(),把實例對象當方法使用 xxx() 將對象看做是函數
枚舉類
from enum import Enum
@unique #檢查有無重復值
class Weekday(Enum):
Sun = 0
Mon = 1
...
print(Weekday.Mon) # 1
元類
from hello import Hello
h = Hello()
h.hello()
- 其中,Hello是一個class,它的類型是type
- h是Hello的實例,它的類型是Hello
- type()可以返回一個實例的類型: type(obj)
- type()也可以創建新的類型,此時就不需要再 class Hello(object)之類的麻煩定義
- type(class名稱,基繼承的父類集合(tuple,),方法名)
def function(self): # 這裡的self必須要有,因為要建類
print("ok")
Hello = type("Hello",(object,),dict(hello=function))
h = Hello()
h.hello()
- metaclass 元類
- 對於類,首先我們定義類,然後創建實例
- metacalss是類的元,先定義metaclass,然後創建類,然後創建實例
- 類是metaclass的實例
- 基本不會用,這個太抽象了,魔術代碼