'super' 对象在 python3 中没有属性“__getattr__”
'super' object has no attribute '__getattr__' in python3
如何用 python 3 和继承覆盖 __getattr__
?
当我使用以下内容时:
class MixinA:
def __getattr__(self, item):
# Process item and return value if known
if item == 'a':
return 'MixinA'
# If it is unknown, pass it along to give
# a chance to another class to handle it
return super().__getattr__(item)
class MixinB:
def __getattr__(self, item):
# Process item and return value if known
if item == 'b':
return 'MixinB'
# If it is unknown, pass it along to give
# a chance to another class to handle it
return super().__getattr__(item)
class Example(MixinA, MixinB):
# main class
pass
我收到这个错误。
>>> e = Example()
>>> e.a
'MixinA'
>>> e.b
'MixinB'
>>> e.c
---------------------------------------------------------------------------
AttributeError Traceback (most recent call last)
...
AttributeError: 'super' object has no attribute '__getattr__'
难道我不能得到引用原始 class 和 属性 的属性错误吗?也就是说:
AttributeError: 'Example' object has no attribute 'c'
PS: 我找到了这个 post 'super' object not calling __getattr__ 但我不确定是否有解决方案
Python 属性检索机制的工作方式是 class __getattr__
被称为 "last resource" 以尝试获取 class __getattr__
实例的属性 class.
您的代码是正确的 - 由于您的 "Example" 的 superclass 而失败 - 在本例中 "object" - 没有 __getattr__
属性。
如果您不在深 class 层次结构中,并且想要为直接从对象继承的 class 执行自定义属性检索(在 Py3 中可以表示为完全没有基础,就像您的情况一样代码) - 如果您的自定义查找失败,只需提高 "AttributeError"。
如果您的意图是让您的自定义搜索优先于 Python 的正常属性检索机制(并且不被称为后备),您应该实施 __getattribute__
而不是__getattr__
.
在这种情况下,基础 class - 对象 - 确实有一个 __getattribute__
方法,你必须为普通属性检索调用 - 问题是你必须为 你想要的一切 - 包括方法名称和你设置的已知属性。即:一些东西:
class Example:
def __init__(self):
self.attrs_to_override = ["attr1", "foo", "bar"]
def docustomstuff(self, attr):
...
def __getattribute__(self, attr):
getter = super().__getattribute__
if attr in getter("attrs_to_override"):
getter("docustomstuff")(attr)
return getter(attr)
简而言之,如果您认为应该实施 __getattribute__
而不是 __getattr__
,那么您可能正在尝试错误的方法,除非在非常特殊的情况下。到目前为止您可能不知道的是:如果所需名称的普通属性不存在,则不会调用 __getattr__
,因此无需在 super[=45 中调用它=](除非 superclass 不是对象并且具有已知的定制)
编辑
或者,以最简单的方式检查下一个超级class是否有__getattr__
:
...
if hasattr(super(), "__getattr__"):
return super().__getattr__(attr)
raise AttributeError
如果你想用 mixin-style classes 做事,那么你需要创建一个 base-attribute-getting-class 总是引发一个 AttributeError
.
class AttrGetter:
def __getattr__(self, item):
raise AttributeError(item)
class MixinA(AttrGetter):
def __getattr__(self, item):
if item == 'a':
return 'MixinA'
return super().__getattr__(item)
class MixinB(AttrGetter):
def __getattr__(self, item):
if item == 'b':
return 'MixinB'
return super().__getattr__(item)
class Example(MixinA, MixinB):
pass
# mro stands for method resolution order.
# It defines the order in which classes are searched for attributes.
# We're looking for __getattr__ in this circumstance.
print(Example.mro())
# [<class '__main__.Example'>, <class '__main__.MixinA'>, <class '__main__.MixinB'>,
# <class '__main__.AttrGetter'>, <class 'object'>]
# As you can see, searches for __getattr__ only check AttrGetter after having checked
# both mixins first.
e = Example()
print(e.a)
print(e.b)
print(e.c)
但是,属性允许您以更简单、更简洁的方式执行此操作。
class MixinA:
@property
def a(self):
return "MixinA"
class MixinB:
@property
def b(self):
return "MixinB"
class Example(MixinA, MixinB):
pass
e = Example()
print(e.a)
print(e.b)
print(e.c)
如何用 python 3 和继承覆盖 __getattr__
?
当我使用以下内容时:
class MixinA:
def __getattr__(self, item):
# Process item and return value if known
if item == 'a':
return 'MixinA'
# If it is unknown, pass it along to give
# a chance to another class to handle it
return super().__getattr__(item)
class MixinB:
def __getattr__(self, item):
# Process item and return value if known
if item == 'b':
return 'MixinB'
# If it is unknown, pass it along to give
# a chance to another class to handle it
return super().__getattr__(item)
class Example(MixinA, MixinB):
# main class
pass
我收到这个错误。
>>> e = Example()
>>> e.a
'MixinA'
>>> e.b
'MixinB'
>>> e.c
---------------------------------------------------------------------------
AttributeError Traceback (most recent call last)
...
AttributeError: 'super' object has no attribute '__getattr__'
难道我不能得到引用原始 class 和 属性 的属性错误吗?也就是说:
AttributeError: 'Example' object has no attribute 'c'
PS: 我找到了这个 post 'super' object not calling __getattr__ 但我不确定是否有解决方案
Python 属性检索机制的工作方式是 class __getattr__
被称为 "last resource" 以尝试获取 class __getattr__
实例的属性 class.
您的代码是正确的 - 由于您的 "Example" 的 superclass 而失败 - 在本例中 "object" - 没有 __getattr__
属性。
如果您不在深 class 层次结构中,并且想要为直接从对象继承的 class 执行自定义属性检索(在 Py3 中可以表示为完全没有基础,就像您的情况一样代码) - 如果您的自定义查找失败,只需提高 "AttributeError"。
如果您的意图是让您的自定义搜索优先于 Python 的正常属性检索机制(并且不被称为后备),您应该实施 __getattribute__
而不是__getattr__
.
在这种情况下,基础 class - 对象 - 确实有一个 __getattribute__
方法,你必须为普通属性检索调用 - 问题是你必须为 你想要的一切 - 包括方法名称和你设置的已知属性。即:一些东西:
class Example:
def __init__(self):
self.attrs_to_override = ["attr1", "foo", "bar"]
def docustomstuff(self, attr):
...
def __getattribute__(self, attr):
getter = super().__getattribute__
if attr in getter("attrs_to_override"):
getter("docustomstuff")(attr)
return getter(attr)
简而言之,如果您认为应该实施 __getattribute__
而不是 __getattr__
,那么您可能正在尝试错误的方法,除非在非常特殊的情况下。到目前为止您可能不知道的是:如果所需名称的普通属性不存在,则不会调用 __getattr__
,因此无需在 super[=45 中调用它=](除非 superclass 不是对象并且具有已知的定制)
编辑
或者,以最简单的方式检查下一个超级class是否有__getattr__
:
...
if hasattr(super(), "__getattr__"):
return super().__getattr__(attr)
raise AttributeError
如果你想用 mixin-style classes 做事,那么你需要创建一个 base-attribute-getting-class 总是引发一个 AttributeError
.
class AttrGetter:
def __getattr__(self, item):
raise AttributeError(item)
class MixinA(AttrGetter):
def __getattr__(self, item):
if item == 'a':
return 'MixinA'
return super().__getattr__(item)
class MixinB(AttrGetter):
def __getattr__(self, item):
if item == 'b':
return 'MixinB'
return super().__getattr__(item)
class Example(MixinA, MixinB):
pass
# mro stands for method resolution order.
# It defines the order in which classes are searched for attributes.
# We're looking for __getattr__ in this circumstance.
print(Example.mro())
# [<class '__main__.Example'>, <class '__main__.MixinA'>, <class '__main__.MixinB'>,
# <class '__main__.AttrGetter'>, <class 'object'>]
# As you can see, searches for __getattr__ only check AttrGetter after having checked
# both mixins first.
e = Example()
print(e.a)
print(e.b)
print(e.c)
但是,属性允许您以更简单、更简洁的方式执行此操作。
class MixinA:
@property
def a(self):
return "MixinA"
class MixinB:
@property
def b(self):
return "MixinB"
class Example(MixinA, MixinB):
pass
e = Example()
print(e.a)
print(e.b)
print(e.c)