【发布时间】:2017-11-29 19:36:03
【问题描述】:
我正在使用的库中有一个我想覆盖的类。看起来是这样的,我改不了:
class A(Q):
def __init__(self):
super().__init__()
self.data = {}
for x in range(10):
self.data[x] = x * x
在我的子类中,我希望 data 根据运行时应用的规则做出不同的行为:
class B(A):
@property
def data(self):
return {x: x*x for x in super().data if x not in some_list_that_changes_at_runtime}
@data.setter
def data(self, value):
super().data = value
很遗憾,这不起作用,至少有两个原因:
1) super().data 似乎实际上无法访问在A 上定义的data 版本。
2) A.__init__ 在self.data = {} 行上崩溃,因为它无法分配给B 定义的data 版本。
3) 从理论上讲,即使我可以让它工作,A.__init__ 中的循环也不会工作,因为它是 getting data 以便在其中分配键/值对.但是这样做 get 将导致@property 被访问,并返回与A.data 不同的对象,这意味着A.data 不会被更改。
我无法编辑A,并且我需要@property 与原始dict 属性具有相同的名称,因为库中的各种其他代码访问data,并且该代码也不能改变了。
我也不能真正覆盖A.__init__ 以使其不与data 混淆,因为我需要Q.__init__ 才能运行。
这里有什么可行的方法来做我想做的事吗?
【问题讨论】:
-
我不明白你想用
super().data = value做什么... -
我认为,而不是
super().data,只需在你的 getter 和 setter 中创建一个私有变量:self._data。但是,这将产生一个问题:当您执行self.data[0] = something时,它返回一个新的dict,然后您将分配给它并立即丢弃。 -
property的实现细节是否会干扰您尝试执行的操作? (这是一个修辞问题;我不知道。但如果有,您也许可以编写自定义描述符,自己实现__get__和__set__。) -
@chepner:当您在描述符上实现
__set__方法时,它就是一个数据描述符,并且将始终覆盖实例属性。
标签: python python-3.x python-decorators