在一个类中,我想将对 inst.addr
的调用映射到通过调用 inst.addr_fun()
创建的值,因此创建了以下代码:
class Common:
...
def __getattr__(self, name):
if hasattr(self, '{}_fun'.format(name)):
return getattr(self, '{}_fun'.format(name))()
else:
raise AttributeError('attribute unknown in instance')
def addr_fun(self):
return 42
但是,它会导致递归,因为 getattr
调用 __getattr__
,所以我无法访问 addr_fun
函数。
如何访问实例中的命名属性?
最佳答案
Python language refererence about __getattr__ :
object.__getattr__(self, name)
Called when an attribute lookup has not found the attribute in the usual places (i.e. it is not an instance attribute nor is it found in the class tree for self). name is the attribute name. This method should return the (computed) attribute value or raise an AttributeError exception.
Note that if the attribute is found through the normal mechanism, __getattr__() is not called. (This is an intentional asymmetry between __getattr__() and __setattr__().) This is done both for efficiency reasons and because otherwise __getattr__() would have no way to access other attributes of the instance. Note that at least for instance variables, you can fake total control by not inserting any values in the instance attribute dictionary (but instead inserting them in another object). See the __getattribute__() method below for a way to actually get total control over attribute access.
这意味着 __getattr__
只有在找不到实例变量、类属性和同名方法时才会被调用。
因此您的代码适用于“addr”。您将获得其他名称的无限递归,因为 hasattr()
also uses __getattr__
.
您应该避免在 __getattr__
中使用 hasattr()
和 getattr()
。
相反,您可以在捕获 AttributeError
的 try-except
block 中使用 super().__getattribute__(name)
。
请注意 super().__getattribute__(name)
不会在父类上调用 __getattr__(name)
。因此,如果您想要支持一个类层次结构,其中 __getattr__
可能链接到另一个类的 __getattr__
方法,您需要调用 super().__getattr__(name)
如果 super.__getattribute__()
失败。
关于python - 如何在 magic __getattr__ 中获取实例属性?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/42065239/