特殊屬性
屬性 |
含義 |
__name__ |
類、函數、方法的名稱 |
__module__ |
類定義所在的模塊名 |
__class__ |
對象或類所屬的類 |
__bases__ |
類的基類的元組,順序為它們在基類列表中出現的順序 |
__doc__ |
類、函數的文檔字符串,若沒定義則為None |
__mro__ |
類的mro,方法查找順序 |
__dict__ |
類或實例的屬性,可寫的字典 |
查看屬性
__dir__:返回類或者對象的所有成員名稱列表,dir()即調用__dir__(),若提供__dir__(),則返回屬性的列表,否則會盡量從__dict__中收集多的信息
若dir([obj])參數obj包含__dir__()方法,該方法被調用。若參數obj不包含__dir__()方法,則將會收集盡量多的參數信息
對不同類型具有不同行為
若對象為模塊對象,返回的列表包含模塊的屬性名
若對象為類型或類對象,返回的列表包含類的屬性名、基類的屬性名
否則,返回列表包含對象的屬性名、類的屬性名、類的基類的屬性名
?
?
魔術方法
分類
創建、初始化、銷毀
__init__、__del__
hash
bool
可視化
運算符重載
容器和大小
可調用對象
上下文管理
反射
描述器
其他
hash
hash的特點
固定大小
雪崩效應
單向不可逆
__hash__:內建函數hash()調用的返回值,返回一個整數,若定義該方法則該類的實例就可hash
__eq__:對應==,判斷兩個對象是否相等,返回bool值
__hash__僅返回一個hash值作為set或dict的key,但去重需要__eq__來判斷2個對象是否相等
hash值相等只是hash沖突,不能說明兩個對象相等
不可hash對象isinstan(obj,collections.Hashable) = False
__hash__ = None:設置類不能被hash
?
?
bool
__bool__:內建函數bool(),或者對象放在邏輯表達式的位置,調用該函數返回bool值,沒定義__bool__()就找__len__()返回長度,長度非0為真,若__len__()也沒有定義,則所有實例均返回真
?
?
可視化
__repr__:內建函數repr()對一個對象獲取字符串表達。調用__repr__方法返回字符串表達,若__repr__沒有定義,就直接返回object的內存地址信息
__str__:str()函數、內建函數format()、print()調用,需要返回對象的字符串表達。若未定義則調用__repr__返回字符串表達,__repr__未定義返回object的內存地址信息
__bytes__:bytes()函數調用,返回一個對象的bytes表達
?
?
運算符重載
<,<=,==,>,>=,!= |
__lt__,__le__,__eq__,__gt__,__ge__,__ne__ |
+,-,*,/,%,//,**,divmod |
__add__,__sub__,__mul__,__trudiv__,__mod__,__floordiv__,__pow__,__divmod__ |
+=,-=,*=,/=,%=,//=,**= |
__iadd__,__isub__,__imul__,__itrudiv__,__imod__,__ifloordiv__,__ipow__ |
@functools.total_ordering裝飾器
__lt__,__le__,__eq__,__gt__,__ge__是比較大小必須實現的方法,但是全寫太麻煩,使用該裝飾器可簡化代碼
要求__eq__必須實現,剩余其他方法實現其一即可
缺點:引入了不需要的方法,影響性能
自己實現只需保證__eq__,__lt__或__gt__,__le__或__ge__五選三實現即可
容器
__len__:內建函數len(),返回對象的長度,若將對象當做容器類看,bool()函數調用時,若沒有__bool__()方法,則看__len__()是否存在,存在返回非0
__iter__:迭代容器時調用,返回一個新的迭代器對象
__contains__:in成員運算符,若未實現就調用__iter__方法遍歷
__getitem__:實現self[key]訪問。序列對象,key接受整數為索引或切片,對于set或dict,key為hashable,可以不存在KeyError異常
__setitem__:設置值
__missing__:字典或其子類使用__getitem__()調用時,key不存在執行該方法
可調用對象
__call__:類中定義一個該方法,實例就可像函數一樣調用
?
?
上下文管理
當一個對象同時實現了__enter__()和__exit__()方法,它就屬于上下文管理的對象
__enter__:進入與此對象相關的上下文,若存在該方法,with語法會將該方法的返回值綁定到as字句中指定的變量上
__exit__():退出與此對象相關的上下文
實例化對象時不會調用__enter__,進入with語句塊調用__enter__方法 –》執行語句體 –》離開with語句塊調用__exit__()方法
安全性
存在異常,enter和exit照樣執行,上下文管理是安全的
方法的參數
__enter__方法沒有參數
__exit__方法有3個參數,與異常相關,沒有異常則3個參數均為None
exc_type,異常類型
exc_value,異常的值
traceback,異常的追蹤信息
__exit__方法返回一個等效True的值,可以壓制異常,否則繼續拋出異常
應用場景
增強功能
在代碼執行的前后增加代碼,以增強其功能,類似裝飾器
資源管理
打開文件需要關閉
權限驗證
在執行代碼前做權限的驗證
contextlib.contextmanager
裝飾器,實現上下文管理,裝飾一個函數,而不用像類一樣實現__enter__()和__exit__()方法
對下面的函數有要求,必須有yield,必須返回一個生成器,且只有一個yield值
該裝飾器接收一個生成器對象作為參數
?
?
若業務邏輯簡單可使用contextlib.contextmanager,若復雜,用類增加__enter__()和__exit__()方法更方便
反射
概述
運行時,區別于編譯時,指的是程序被加載到內存中執行的時候
反射,reflection,指的是運行時獲取類型定義信息
在Python中,能通過一個對象,找出其type、class、attribute或method的能力,稱為反射或自省
具有反射能力的函數:type()、isinstance()、callable()、dir()、getattr()
相關函數及方法
通過屬性字典__dict__可以訪問對象的屬性,本質上就是利用反射的能力
內建函數 |
意義 |
getattr(object, name[, default]) -> value |
通過name返回object的屬性值,當屬性不存在返回default,若無default則拋出AttributeError,name必須為字符串 |
setattr(obj, name, value) |
object的屬性存在則覆蓋,不存在則新增 |
hasattr(obj, name) |
判斷對象是否有該屬性,name必須為字符串 |
?
?
這種動態增刪屬性的方式是運行時改變類或實例的方式,但裝飾器或Mixin在定義時就寫定了,反射具有更大的靈活性
反射相關魔術方法
__getattr__():一個類的屬性會按照繼承關系查找屬性,若找不到,就會執行__getattr__()方法,如果沒有該方法,則拋出AttributeError
屬性查找順序:instance.__dict__ ——》 instance.__class__.__dict__ ——》繼承的祖先類(直到object)的__dict__ ——》找不到 ——》調用__getattr__()
__setattr__():實例通過.點設置屬性,如self.x = x就會調用__setattr__()。若屬性要加到實例自己的__dict__中,就需要自己完成
__setattr__()方法可以攔截對實例屬性的增加、修改操作,若要設置生效,就需要自己操作實例的__dict__
__delattr__():可以阻止通過實例刪除屬性的操作,但通過類依然可以刪除屬性
__getattribute__:實例的所有屬性訪問,都會第一個調用__getattribute__方法,它阻止了屬性的查找,該方法應該返回一個值(計算后的)或拋出一個AttributeError異常
該方法的return值將作為屬性查找的結果。如果拋出AttributeError,則會直接調用__getattr__方法,表示屬性沒有找到
__getattribute__方法中為了避免該方法出現無限遞歸,其實現應該永遠調用基類的同名方法以訪問需要的任何屬性
魔術方法 |
意義 |
__getattr__() |
當通過搜索實例、實例的類及祖先類查不到屬性時,就會調用該方法 |
__setattr__() |
通過.訪問實例屬性,進行增加、修改 |
__delattr__() |
當通過實例來刪除屬性時調用此方法 |
__getattribute__() |
實例的所有屬性調用都從此方法開始 |
屬性查找順序:實例調用__getattribute__() ——》instance.__dict__——》instance.__class__.__dict__ ——》繼承的祖先類(直到object)的__dict__ ——》調用__getattr__()
描述器
class A含有__get__、__set__、__delete__方法中的任意一個,class B的類屬性x為class A的實例,對class B或B的實例的x屬性的讀取,成為對class A的實例的訪問,就會調用class A中的方法,只有類屬性是class A的實例才會調用class A中的方法
描述器的表現
3個魔術方法:__get__()、__set__()、__delete__()
方法簽名
object.__get__(self,instance,owner)
object.__set__(self,instance,value)
object.__delete__(self,instance)
其中,self指代當前實例,調用者;instance是owner的實例;owner是屬性所屬的類
描述器定義
一個類實現了__get__、__set__、__delete__三個方法中的任何一個,就是描述器
若僅實現__get__,即為非數據描述器non-data descriptor
同時實現__get__、__set__就是數據描述器data descriptor
若一個類的類屬性設置為描述器,則它被稱為owner屬主
屬性的訪問順序
數據描述器 ——》實例的__dict__ ——》非數據描述器
本質:若類屬性指代的是數據描述器,則實例中和類屬性同名的屬性將從__dict__中被刪除,造成數據描述器優先訪問的假象
??
原創文章,作者:ZBD20,如若轉載,請注明出處:http://www.www58058.com/99067