前言
python語言的五個魔術方法,他們都與Python屬性相關,涉及擷取、删除和修改。
__getattribute__方法
源碼如下:
實戰演練:
①首先定義一個類并通路類的對象屬性:
class User:
def __init__(self, name, sex):
self.name = name
self.sex = sex
u1 = User(name='li', sex='male')
print(u1.name)
運作結果:
②接着在該類中加入 __getattribute__
class User:
def __getattribute__(self, item):
return '無論對象是否存在該屬性,都會傳回此值'
def __init__(self, name, sex):
self.name = name
self.sex = sex
u1 = User(name='li', sex='male')
print(u1.name)
print(u1.age)
運作結果:【因為User類中的 __getattribute__ 魔方方法重寫了基類object類的方法,是以此時的 __getattribute__
__getattribute__
①觸發時間:在通路對象成員屬性的時候觸發,無論對象的成員屬性是否存在。
②作用:對屬性進行一些處理。
③參數:
- self為目前對象;
- item是通路屬性名稱的字元串。
④傳回值:對象的屬性值。
【注意】
① __getattribute__方法的是傳回值千萬不能用 self.name
例如:
class User:
def __getattribute__(self, item):
return self.name
def __init__(self, name, sex):
self.name = name
self.sex = sex
u1 = User('li', 'male')
print(u1.name)
運作結果:
②可以使用 object.__getattribute__
例如:
class User:
def __getattribute__(self, item):
return object.__getattribute__(self, item)
def __init__(self, name, sex):
self.name = name
self.sex = sex
u1 = User('li', 'male')
print(u1.name)
運作結果:
__getattr__方法
- 觸發時間:在通路不存在的對象屬性的時候觸發。
- 作用:通路不存在的屬性時候,不會報錯。
- 參數:self為目前對象,item是通路屬性名稱的字元串。
- 傳回值:屬性值。
我們舉個簡單例子,就是使用者可能會輸出屬性名稱,那我們都統一傳回name屬性。
class User:
def __getattr__(self, item):
return self.name
def __init__(self, name, sex):
self.name = name
self.sex = sex
u1 = User('li', 'male')
print(u1.na2me)
li
__setattr__方法
- 觸發時間:添加和修改對象屬性的時候觸發。
- 作用:限制添加和修改對象屬性的操作。
- 參數:self為目前對象,key為設定對象屬性名稱, value為設定的值。
- 傳回值:無。
例如,我們讓使用者可以改name,不能改sex。
__delattr__方法
- 觸發時間:删除對象屬性的時候觸發。
- 作用:限制添加和修改對象屬性的操作。
- 參數:self為目前對象,item為删除對象屬性名稱。
- 傳回值:無。
例如:我們可以讓使用者删除sex,但是不能删除name。
class User:
def __delattr__(self, item):
if item == 'sex':
pass
else:
object.__delattr__(self, item)
def __init__(self, name, sex):
self.name = name
self.sex = sex
u1 = User('li', 'male')
del u1.sex
print(u1.sex)
del u1.name
print(u1.name)
male
AttributeError: 'User' object has no attribute 'name'
__dir__方法以及Python __dict__與dir()差別
Python下一切皆對象,每個對象都有多個屬性(attribute),Python對屬性有一套統一的管理方案。
__dict__與dir()
的差別:
- dir()是一個函數,傳回的是list;
-
是一個字典,鍵為屬性名,值為屬性值;__dict__
- dir()用來尋找一個對象的所有屬性,包括
中的屬性,__dict__
是dir()的子集;__dict__
dir()是Python提供的一個API函數,dir()函數會自動尋找一個對象的所有屬性(包括從父類中繼承的屬性)。
一個執行個體的
__dict__
屬性僅僅是那個執行個體的執行個體屬性的集合,并不包含該執行個體的所有有效屬性。是以如果想擷取一個對象所有有效屬性,應使用dir()。
print dir(A)
'''
['__class__', '__delattr__', '__dict__', '__doc__', '__format__', '__getattribute__', '__hash__', '__init__', '__module__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__sizeof__', '__str__', '__subclasshook__', '__weakref__', 'age', 'class_f', 'class_var', 'fun', 'level1', 'level2', 'name', 'num', 'static_f']
'''
a_dict = a.__dict__.keys()
A_dict = A.__dict__.keys()
object_dict = object.__dict__.keys()
print a_dict
print A_dict
print object_dict
'''
['fun', 'level1', 'age', 'name']
['__module__', 'level2', 'num', 'static_f', '__dict__', '__weakref__', '__init__', 'class_f', 'class_var', 'fun', '__doc__']
['__setattr__', '__reduce_ex__', '__new__', '__reduce__', '__str__', '__format__', '__getattribute__', '__class__', '__delattr__', '__subclasshook__', '__repr__', '__hash__', '__sizeof__', '__doc__', '__init__']
'''
#因為每個類都有一個__doc__屬性,是以需要去重,去重後然後比較
print set(dir(a)) == set(a_dict + A_dict + object_dict) #True
屬性通路順序
最後,屬性通路的順序如下:
- __getattribute__
- 資料描述符
- 目前對象的屬性
- 類的屬性
- 非資料描述符
- 父類的屬性
- __getattr__