【问题标题】:Python - how to access instance properties in parent classes with super(<class>, self)?Python - 如何使用 super(<class>, self) 访问父类中的实例属性?
【发布时间】:2021-05-24 12:27:29
【问题描述】:

请解释为什么我不能使用super(class, self) 来访问在类继承层次结构中较高的类中定义的属性,以及如何访问它们。

根据文档,super(class, self 应该返回一个代理对象,通过它我可以访问父类实例中的def name()

返回一个代理对象,它将方法调用委托给父对象或 类型的兄弟类。这对于访问继承的方法很有用 已在类中被覆盖。

对象或类型决定方法解析顺序 搜索。搜索从类型之后的类开始。

例如,如果 mro 的 object-or-type 是 D -> B -> C -> A -> object 且 type 的值为 B,则 super() 搜索 C -> A -> 对象。

我认为super(Parent) 会给具有def name() 的GrandParent 对象提供代理。

class GrandParent:
    def __init__(self):
        self._name = "grand parent"

    @property
    def name(self):
        return self._name


class Parent(GrandParent):
    def __init__(self):
        super().__init__()
        self._name = "parent"

    @property
    def name(self):
        return super().name


class Child(Parent):
    def __init__(self):
        super().__init__()
        self._name = "child"

    @property
    def name(self):
        return super(Parent).name


print(Child().name)
---
AttributeError: 'super' object has no attribute 'name'

没有(class, self),它返回...子属性。显然我还没有理解 selfsuper 在 Python 中是如何工作的。请建议要研究哪些资源以充分了解行为和设计。

class GrandParent:
    def __init__(self):
        self._name = "grand parent"

    @property
    def name(self):
        return self._name


class Parent(GrandParent):
    def __init__(self):
        super().__init__()
        self._name = "parent"

    @property
    def name(self):
        return super().name


class Child(Parent):
    def __init__(self):
        super().__init__()
        self._name = "child"

    @property
    def name(self):
        return super().name


print(Child().name)
---
child

【问题讨论】:

  • 没有“超级名称”。所有name 属性只返回self._name,其中只有一个。您的对象的每个父对象都没有一个 _name 属性。

标签: python class super


【解决方案1】:

self 总是指同一个对象。当您执行super().__init__() 时,父级__init__ 中的self 是您的Child 实例。 GrandParent.__init__ 只是在该对象上设置一个属性。通过链接所有__init__s,您实际上只是在这样做:

o = object()
o._name = 'grand parent'
o._name = 'parent'
o._name = 'child'

您只是覆盖 _name 属性,其中只有一个。所有不同的@propertys 只是返回这一个_name 属性的值,你的对象只有一个,其值为'child'

如果您希望您的对象的每个父对象都有一个单独的 _name 属性,那么您实际上必须创建单独的属性。最简单的方法可能是使用 Python 的双下划线 name mangling 又名“私有属性”:

>>> class A:
...   def __init__(self):
...     self.__foo = 'bar'
...   @property
...   def foo(self):
...     return self.__foo
...
>>> class B(A):
...   def __init__(self):
...     super().__init__()
...     self.__foo = 'baz'
...   @property
...   def foo(self):
...     return super().foo
... 
>>> B().foo
'bar'
>>> vars(B())
{'_A__foo': 'bar', '_B__foo': 'baz'}

实际属性名为_A__foo_B__foo,因此不会相互冲突。

【讨论】:

    猜你喜欢
    • 2021-11-07
    • 1970-01-01
    • 2017-10-24
    • 2021-04-25
    • 2016-06-10
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多