1、python的魔法方法
魔法方法是指Python內部已經包含的,被雙下劃線所包圍的方法,這些方法在進行特定的操作時會自動被調用,它們是Python面向對象下智慧的結晶
2、關於屬性的魔法方法
- __ getattribute __(self, name)----定義了屬性被訪問時的行爲,而__getattr__只有該屬性不存在時纔會起作用,因此,在支持__getattribute__的Python版本,調用__getattr__前必定會調用 __ getattribute __,調用時應注意避免"無限遞歸"的錯誤。
- __ getattr __(self, name)----該方法定義了你試圖訪問一個不存在的屬性時的行爲。因此,重載該方法可以實現捕獲錯誤拼寫然後進行重定向, 或者對一些廢棄的屬性進行警告。
- __ setattr __(self, name, value)----是實現封裝的解決方案,它定義了你對屬性進行賦值和修改操作時的行爲。不管對象的某個屬性是否存在,它都允許你爲該屬性進行賦值,因此你可以爲屬性的值進行自定義操作,但是要注意避免"無限遞歸"的錯誤。
- __ delattr __(self, name)----定義的是刪除屬性時的行爲,調用時注意避免"無限遞歸"的錯誤。
classAccess(object):
def__getattr__(self, name):
print '__getattr__'
return super(Access, self).__getattr__(name)
def__setattr__(self, name, value):
print '__setattr__'
return super(Access, self).__setattr__(name, value)
def__delattr__(self, name):
print '__delattr__'
return super(Access, self).__delattr__(name)
def__getattribute__(self, name):
print '__getattribute__'
return super(Access, self).__getattribute__(name)
access = Access()
access.attr1 = True # __setattr__調用
access.attr1 # 屬性存在,只有__getattribute__調用
try:
access.attr2 # 屬性不存在, 先調用__getattribute__, 後調用__getattr__
except AttributeError:
pass
del access.attr1 # __delattr__調用
- 無限遞歸錯誤
# 以上例子都是,每一次屬性賦值時, 方法都會被調用,因此不斷調用自身導致無限遞歸了
def __setattr__(self, name, value):
self.name = value
def __getattribute__(self, item):
print('__getattribute__')
return self.item
def __getattribute__(self, name):
return self.__dict__[name]
# 正確的寫法
def __setattr__(self, name, value):
self.__dict__[name] = value
def __getattribute__(self, item):
print('__getattribute__')
return super().__getattribute__(self, item)
3、實例對象屬性尋找的順序
- 首先訪問 __ getattribute __() 魔法方法(隱含默認調用,無論何種情況,均會調用此方法)。
- 接着,去t.__dict__中查找是否具備該屬性。
- 若在 t.__ dict __ 中找不到對應的屬性, 則去t.__ class __.__dict__中尋找。
- 若在實例的類中也找不到該屬性,則去父類中尋找,即 t.__ class . bases __.__dict__中尋找。
- 若以上均無法找到,則會調用 __ getattr __ 方法,執行內部的命令(若未重載 __ getattr __ 方法,則直接報錯:AttributeError)
class Test:
def __getattr__(self, item):
print('__getattr__')
def __getattribute__(self, item):
print('__getattribute__')
#super().__getattribute__(item)
#object.__getattribute__(self,item)
def __setattr__(self, item, value):
print('__setattr__')
def __delattr__(self, item):
print('__delattr__')
t = Test()
t.x
#__getarrtribute__
以上這個程序在訪問一個不存在的屬性的時候並沒有調用__ getattr __ ,而只是調用了__ getatrrribute __ 。這個的問題就出在了步驟的第④步,因爲,一旦重載了 __ getattribute __ () 方法,如果找不到屬性,則必須要手動加入第④步,否則是無法進入到 第⑤步 (__ getattr __)的。
- 方法一:採用 object(所有類的基類)
class Test:#父類
def __getattr__(self, item):
print('__getattr__')
def __getattribute__(self, item):
print('__getattribute__')
#super().__getattribute__(item)
object.__getattribute__(self,item)
def __setattr__(self, item, value):
print('__setattr__')
def __delattr__(self, item):
print('__delattr__')
t = Test()
t.x
#__getattribute__
#__getattr__
- 方法二:採用 super() 方法
class Test:#父類
def __getattr__(self, item):
print('__getattr__')
def __getattribute__(self, item):
print('__getattribute__')
super().__getattribute__(item)
#object.__getattribute__(self,item)
def __setattr__(self, item, value):
print('__setattr__')
def __delattr__(self, item):
print('__delattr__')
t = Test()
t.x
#__getattribute__
#__getattr__
4、一些基礎魔法方法
5、屬性相關的方法
6、比較操作符
7、算數運算符
參考文獻
- https://blog.csdn.net/LSGO_MYP/article/details/102573292
- https://blog.csdn.net/qq_38520096/article/details/79237593
- https://www.cnblogs.com/zhouyixian/p/11129347.html
- https://www.cnblogs.com/blackmatrix/p/5681480.html