Python - 如何使用 super(, self) 访问父类中的实例属性<class>?



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

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

  • super([type[,object or type]])

返回一个代理对象,该对象将方法调用委托给父对象或类型的同级类。这对于访问继承的方法很有用已在类中重写的。

对象或类型确定要执行的方法解析顺序已搜索。搜索从类型后面的类开始。

例如,如果对象或类型的mro是D->B->C->A->对象,并且类型的值为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

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

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

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

如果希望对象每个父对象都有一个单独的_name属性,那么实际上必须创建单独的属性。最简单的方法可能是使用Python的双下划线名称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,因此彼此不冲突。

最新更新