Python - 如何使用 super(<class>, self) 访问 parent 类 中的实例属性?
Python - how to access instance properties in parent classes with super(<class>, self)?
请解释为什么我不能使用 super(class, self)
访问 class 继承层次结构中更高层 class 中定义的属性,以及如何访问它们。
根据文档,super(class, self
应该返回一个代理 object,通过它我可以访问 parent class 实例中的 def name()
。
Return a proxy object that delegates method calls to a parent or
sibling class of type. This is useful for accessing inherited methods
that have been overridden in a class.
The object-or-type determines the method resolution order to be
searched. The search starts from the class right after the type.
For example, if mro of object-or-type is D -> B -> C -> A ->
object and the value of type is B, then super() searches C -> A ->
object.
我认为 super(Parent)
会为具有 def name()
.
的祖父母 object 提供代理
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)
,它returns ... child 属性。显然我还没有理解 self
和 super
在 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__
中的 self
就是您的 Child
实例。 GrandParent.__init__
只是在该对象上设置一个属性。通过链接所有这些 __init__
s,你实际上只是这样做:
o = object()
o._name = 'grand parent'
o._name = 'parent'
o._name = 'child'
您只是覆盖 _name
属性,其中只有一个。所有不同的 @property
只是 return 这个 _name
属性的值,你的对象只有一个,它的值是 'child'
.
如果您希望对象的每个父对象都有一个单独的 _name
属性,您实际上必须创建单独的属性。最简单的方法可能是使用 Python 的双下划线 name mangling a.k.a。 “私有属性”:
>>> 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
,因此不会相互冲突。
请解释为什么我不能使用 super(class, self)
访问 class 继承层次结构中更高层 class 中定义的属性,以及如何访问它们。
根据文档,super(class, self
应该返回一个代理 object,通过它我可以访问 parent class 实例中的 def name()
。
Return a proxy object that delegates method calls to a parent or sibling class of type. This is useful for accessing inherited methods that have been overridden in a class.
The object-or-type determines the method resolution order to be searched. The search starts from the class right after the type.
For example, if mro of object-or-type is D -> B -> C -> A -> object and the value of type is B, then super() searches C -> A -> object.
我认为 super(Parent)
会为具有 def name()
.
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)
,它returns ... child 属性。显然我还没有理解 self
和 super
在 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__
中的 self
就是您的 Child
实例。 GrandParent.__init__
只是在该对象上设置一个属性。通过链接所有这些 __init__
s,你实际上只是这样做:
o = object()
o._name = 'grand parent'
o._name = 'parent'
o._name = 'child'
您只是覆盖 _name
属性,其中只有一个。所有不同的 @property
只是 return 这个 _name
属性的值,你的对象只有一个,它的值是 'child'
.
如果您希望对象的每个父对象都有一个单独的 _name
属性,您实际上必须创建单独的属性。最简单的方法可能是使用 Python 的双下划线 name mangling a.k.a。 “私有属性”:
>>> 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
,因此不会相互冲突。