简体   繁体   English

'super'对象在python3中没有属性'__getattr__'

[英]'super' object has no attribute '__getattr__' in python3

How to override __getattr__ with python 3 and inheritance? 如何用python 3和继承覆盖__getattr__

When I use the following: 当我使用以下内容时:

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

I get this error. 我收到这个错误。

>>> e  = Example()
>>> e.a
'MixinA'
>>> e.b
'MixinB'
>>> e.c
---------------------------------------------------------------------------
AttributeError                            Traceback (most recent call last)
...
AttributeError: 'super' object has no attribute '__getattr__'  

Couldn't I just get the attribute error referencing the original class and property? 难道我只能获取引用原始类和属性的属性错误吗? That is to say: 也就是说:

AttributeError: 'Example' object has no attribute 'c'

PS: I found this post 'super' object not calling __getattr__ but I'm not sure to understand whether there is a solution. PS:我发现这个帖子'超级'对象没有调用__getattr__但是我不确定是否有解决方案。

The Python attribute retrieval mechanism works in a way that a class __getattr__ is called as "last resource" to try to get an attribute for an instance of that class. Python属性检索机制的工作方式是将类__getattr__称为“最后一个资源”,以尝试获取该类实例的属性。

Your code is right - it fails due to your superclass of "Example" - in this case "object" - not having a __getattr__ attribute. 你的代码是正确的 - 由于你的超级类“示例” - 在这种情况下是“对象” - 没有__getattr__属性,它失败了。 If you are not at a deep class hierarchy and want to perform custom attribute retrieval for a class inheriting directly from object (which in Py3 can be expressed as having no bases at all as is the case in your code) - just raise "AttributeError" if your custom lookup failed. 如果您不是深层次的层次结构,并且想要为直接从对象继承的类执行自定义属性检索(在Py3中可以表示为根本没有任何基础,就像在代码中那样) - 只需引发“AttributeError”如果您的自定义查找失败。

If your intention is to, instead, make yur custom search have priority over Python's normal attribute retreival mechanism (and not be called as a fallback) you should implement __getattribute__ instead of __getattr__ . 相反,如果你的意图是使自定义搜索优先于Python的普通属性retreival机制(而不是被称为回退),你应该实现__getattribute__而不是__getattr__

In this case, the base class - object - does have a __getattribute__ method you have to call for ordinary attribute retrieval - the problem is that you have to call it for everything you want - including method names, and known attributes you had set. 在这种情况下,基类 - 对象 - 确实有一个__getattribute__方法,你必须调用普通属性检索 - 问题是你必须为你想要的一切调用它 - 包括方法名称和你设置的已知属性。 ie: something along: 即:某事:

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)

In short, if you think you should implement __getattribute__ instead of __getattr__ you probably are trying the wrong approach, except in very specific cases. 简而言之,如果您认为应该实现__getattribute__而不是__getattr__那么您可能正在尝试错误的方法,除非在非常具体的情况下。 What you probably didn't know up to here is that: __getattr__ would not have been called if an ordinary attribute by the wanted name did not already exist, so there is no need to call it in the superclass (unless the superclass in case is not object and has a known customization for it) 你可能在这里不知道的是:如果所需名称的普通属性不存在,则不会调用__getattr__ ,因此不需要在超类中调用它(除非超类是大小写的)不是对象,并具有已知的自定义)

edit 编辑

Alternatively, just check if the next superclass do have __getattr__ in the most plain way: 或者,只需检查下一个超类是否以最简单的方式拥有__getattr__

...
if hasattr(super(), "__getattr__"):
    return super().__getattr__(attr)
raise AttributeError

If you want to do things with mixin-style classes then you need to create a base-attribute-getting-class that always raises an AttributeError . 如果你想用mixin风格的类做事,那么你需要创建一个始终引发AttributeError的base-attribute-getting-class。

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)

However, properties allow you to do this in much easier and more succinct way. 但是,属性允许您以更简单,更简洁的方式执行此操作。

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)

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 AttributeError: &#39;super&#39; 对象在 python 中没有属性 &#39;__getattr__&#39; - AttributeError: 'super' object has no attribute '__getattr__' in python Python Kivy 返回 'AttributeError: 'super' object 没有属性 '__getattr__'' - Python Kivy returning 'AttributeError: 'super' object has no attribute '__getattr__'' python kivy AttributeError:“超级”对象没有属性“ __getattr__” - python kivy AttributeError: 'super' object has no attribute '__getattr__' AttributeError:“超级”对象没有属性“ __getattr__” - AttributeError: 'super' object has no attribute '__getattr__' 'super' object 在 kivymd 中没有属性 '__getattr__' - 'super' object has no attribute '__getattr__' in kivymd AttributeError:“超级”对象没有属性“ __getattr __”(我进行了搜索,但无济于事) - AttributeError: 'super' object has no attribute '__getattr__' ( I searched, but to no avail) Kivy: AttributeError: 'super' object 没有属性 '__getattr__' - Kivy: AttributeError: 'super' object has no attribute '__getattr__' Kivy AttributeError: 'super' object 没有属性 '__getattr__' - Kivy AttributeError: 'super' object has no attribute '__getattr__' Kivy AttributeError: 'super' object has no attribute '__getattr__' 错误 - Kivy AttributeError: 'super' object has no attribute '__getattr__' error 'super' object 没有属性 '__getattr__',谁能帮帮我? - 'super' object has no attribute '__getattr__', can anyone help me?
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM