setattr(x,y,z) ----> x.y=z
setattr(Test,'x'.1) Test 爲類對象
getattr(object,name[,default])
getattr(x,'y') -----> x.y
不會觸發__getattribute__
__getattr__:
如果實例instance
通過instance.name
訪問屬性name,
如果類中沒有定義name,會觸發此方法,
類中定義了name 這個屬性,不會觸發此方法
注意:如果在__getattr__(self, attr)
存在通過self.attr
訪問屬性,會出現無限遞歸錯誤。
__getattribute__
如果實例instance
通過instance.name
訪問屬性name,
不管類中有沒有定義name 屬性,都會觸發此方法,
注意:如果在__getattribute__(self, attr)
方法下存在通過self.attr
訪問屬性,會出現無限遞歸錯誤
如果類中定義了__getattr__
方法,除非通過__getattribute__
顯式的調用它,或者__getattribute__
方法出現AttributeError
錯誤,否則__getattr__
方法不會被調用
- test.x =1
- print(test.x) 設置/訪問屬性 每次都會調用 __getattribute__方法
test.x =1 ---->調用__setattr__,不建議自己實現
print(test.x) ====> 如果x屬性沒有設置__getattribute__會去調用 __getattr__方法
class Test1:
def __init__(self):
self.s = 2
def __getattr__(self, key):
print("__getattr___", key)
if key == 'x':
return 'default x'
return key
T = Test1()
print(T.s)
#輸出
# 2
print(T.f) #類沒有f屬性,就調用了__getattr__
#輸出
#__getattr___ f
#f
class Test3():
def __init__(self):
self.s = 2
def __getattribute__(self, key):
print('__getattribute__')
if key == 'x':
return 'default x'
else:
return key
----------------------
T =Test3() #不管類裏有沒有該屬性 都調用了__getattribute__
print(T.s)
#輸出:
#__getattribute__
#s
print(T.x)
# 輸出
# __getattribute__
# default
# x
class Test2:
def __init__(self):
self.s = 2
def __getattribute__(self, key):
print('__getattribute__')
if key == 'x':
pass
# return 'default x'
else:
raise AttributeError
def __getattr__(self, key):
print("__getattr___", key)
return key
--------------------------------
T = Test2()
#輸出
# print(T.x)
#__getattribute__
#None
print(T.f) # __getattribute__ 拋出AttributeError,調用 __getattr___
#輸出
# __getattribute__
# __getattr___ f
# f