Python類属性アクセスの魔法方法
4730 ワード
Python類属性アクセスの魔法方法:
1. __getattr__(self,name)-ユーザーが存在しない属性を取得しようとしたときの動作を定義します.
2. __getattribute__(self,name)-クラスのプロパティがアクセスされたときの動作を定義します.
注意:getattr__と_getattribute__同時に書き換える場合、属性にアクセスする場合、優先的に__を呼び出すgetattribute__,アクセスされた属性が存在しない場合にのみトリガーされます.getattr__
3. __setattr__(self,name,value)-プロパティが設定されているときの動作を定義します.
4. __delattr__(self,name)-属性が削除されたときの動作を定義します.
また、_setattr__デッドサイクルトラップがあります.
どうしてこんなことになったの?
主に_init__内、widthとheightに値を付けると自動的にトリガーされます_setattr__メソッドは、パラメータ2,8がwidthとheightにそれぞれ入力されたときに初期化されると、付与トリガ_setattr__,2はwidth属性に渡されるのでsuqareではなくelseの文(self.name=value)が実行されますが、elseの文はまた付与文であり、自動的に__がトリガーされますsetattr__,だから、死の循環をもたらします.その解決方法は2つあります.
1.self.name=valueこの文はsuper(.)に変更されました.setattr__(name,value),親クラスの__を使用setattr__(なぜループしないの?聞かないで、どうせPythonの設計者がこの問題を解決した)
2.self.name=valueこの文はself._に変更されました.dict__[name]=value、これも賦値ですが、なぜ死循環ではないのでしょうか.ハハ、トリガー_setattr__の場合はアクセスオブジェクトのプロパティですが、ここではたまたまアクセスするのは__です.dict__(オブジェクトの特殊な属性は、現在のオブジェクトを格納するための属性の辞書です).
1. __getattr__(self,name)-ユーザーが存在しない属性を取得しようとしたときの動作を定義します.
2. __getattribute__(self,name)-クラスのプロパティがアクセスされたときの動作を定義します.
注意:getattr__と_getattribute__同時に書き換える場合、属性にアクセスする場合、優先的に__を呼び出すgetattribute__,アクセスされた属性が存在しない場合にのみトリガーされます.getattr__
3. __setattr__(self,name,value)-プロパティが設定されているときの動作を定義します.
4. __delattr__(self,name)-属性が削除されたときの動作を定義します.
>>> class C:
def __getattribute__(self, name):
print("getattribute")
return super().__getattribute__(name) # return , ,c.x __getattr__ , c.x
def __getattr__(self, name):
print("getattr")
def __setattr__(self, name, value):
print("setattr")
super().__setattr__(name, value) # , , 。 :self.name = value? __setattr__
def __delattr__(self, name):
print("delattr")
# super().__delattr__(name), , ,
>>> c = C()
>>> c.x
getattribute
getattr
>>> c.x = 999
setattr
>>> c.x
getattribute
999
>>> del c.x
delattr
# c.x, , , , __delattr__ super().__delattr__(name)
>>> c.x
getattribute
999
>>>
また、_setattr__デッドサイクルトラップがあります.
>>> class Rect():
def __init__(self, width=0, height=0):
self.width = width
self.height = height
def __setattr__(self, name, value):
if name == 'square':
self.width = value
self.height = value
else:
self.name = value
def getArea(self):
return self.width * self.height
>>> r = Rect(2,8)
Traceback (most recent call last):
File "<pyshell#144>", line 1, in <module>
r = Rect(2,8)
File "<pyshell#143>", line 3, in __init__
self.width = width
File "<pyshell#143>", line 10, in __setattr__
self.name = value
File "<pyshell#143>", line 10, in __setattr__
self.name = value
File "<pyshell#143>", line 10, in __setattr__
self.name = value
File "<pyshell#143>", line 10, in __setattr__
……
どうしてこんなことになったの?
主に_init__内、widthとheightに値を付けると自動的にトリガーされます_setattr__メソッドは、パラメータ2,8がwidthとheightにそれぞれ入力されたときに初期化されると、付与トリガ_setattr__,2はwidth属性に渡されるのでsuqareではなくelseの文(self.name=value)が実行されますが、elseの文はまた付与文であり、自動的に__がトリガーされますsetattr__,だから、死の循環をもたらします.その解決方法は2つあります.
1.self.name=valueこの文はsuper(.)に変更されました.setattr__(name,value),親クラスの__を使用setattr__(なぜループしないの?聞かないで、どうせPythonの設計者がこの問題を解決した)
2.self.name=valueこの文はself._に変更されました.dict__[name]=value、これも賦値ですが、なぜ死循環ではないのでしょうか.ハハ、トリガー_setattr__の場合はアクセスオブジェクトのプロパティですが、ここではたまたまアクセスするのは__です.dict__(オブジェクトの特殊な属性は、現在のオブジェクトを格納するための属性の辞書です).