【发布时间】:2016-05-19 08:22:42
【问题描述】:
这里是 Python 3,以防万一它很重要。
我试图正确理解在使用@property 时如何实现继承,并且我已经搜索了 StackOverflow 并阅读了 20 个类似的问题,但无济于事,因为他们试图解决的问题略有不同。这是我用于测试的代码:
class Example:
def __init__(self):
self.__data = None
@property
def data(self):
return self.__data
@data.setter
def data(self, data):
self.__data = data
class Example2(Example):
def __init__(self):
super().__init__()
@property
def data(self):
return super().data # Works!
@data.setter
def data(self, data):
data = '2' + data
#Example.data = data # Works, but I want to avoid using the parent name explicitly
#super().data = data # Raises AttributeError: 'super' object has no attribute 'data'
#super().data.fset(self, data) # Raises AttributeError: 'NoneType' object has no attribute 'fset'
#super(self.__class__, self.__class__).data = data # Raises AttributeError: 'super' object has no attribute 'data'
super(self.__class__, self.__class__).data.fset(self, data) # Works!
a = Example2()
a.data = 'element a'
print(a.data)
我不明白为什么super().data 在Example2 getter 中有效,但在setter 中无效。我的意思是,为什么在 setter 中需要一个类绑定方法,而在 getter 中需要一个实例绑定方法?
谁能给我一个解释或解释为什么我在测试的五个不同电话中的三个中得到AttributeError?
是的,我知道,我可以在 setter 中使用 Example.data,但在 getter 中不需要这样做,并且 a) 如果可能,我不希望显式使用父类名称,并且 b) 我不明白getter 和 setter 之间的不对称性。
【问题讨论】:
-
我认为这个问题已经有一段时间了...stackoverflow.com/a/13599342/1345165。显然,唯一的方法是显式使用父类名
-
你真的不应该在
super()调用中使用self.__class__,请参阅When calling super() in a derived class, can I pass in self.__class__? -
您的最后一次调用有效,因为将 类对象 传递给
super()会为该类生成一个代理,并且访问类上的属性名称会返回原始属性目的。所以super(Example2, Example2).data返回原始属性,所以你可以访问.fset。或者你可以用super(Example2, Example2).__set__(self, new_value)绑定属性。 -
如果您只想覆盖 getter 或只覆盖 setter 但继承其他属性挂钩,请参阅Python overriding getter without setter
-
@dnaranjo,这个问题是我读到的问题之一,我认为已经解决了。看来我错了。谢谢:)
标签: python python-3.x inheritance super