Python 在子类中使用@property重写字典属性
我正在使用的库中有一个类,我想重写它。看起来是这样的,我无法改变:Python 在子类中使用@property重写字典属性,python,python-3.x,python-decorators,Python,Python 3.x,Python Decorators,我正在使用的库中有一个类,我想重写它。看起来是这样的,我无法改变: class A(Q): def __init__(self): super().__init__() self.data = {} for x in range(10): self.data[x] = x * x 在我的子类中,我希望数据根据运行时应用的规则表现出不同的行为: class B(A): @property def da
class A(Q):
def __init__(self):
super().__init__()
self.data = {}
for x in range(10):
self.data[x] = x * x
在我的子类中,我希望数据
根据运行时应用的规则表现出不同的行为:
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.uuu init_uuu
在self.data={}
行上崩溃,因为它无法分配给B
定义的data
版本
3) 理论上,即使我可以让它工作,A.\uuuu init\uuuu
中的循环也不会工作,因为它获取数据
,以便在其中分配键/值对。但是这样做会导致访问@属性
,并返回与a.data
不同的对象,这意味着a.data
不会被更改
我无法编辑A
,我需要@属性
与原始dict属性具有相同的名称,因为库中的各种其他代码访问数据
,并且该代码也无法更改
我也不能真正重写A.\uuuuu init\uuuu
以使其不与数据混为一谈,因为我需要运行Q.\uuuu init\uuuu
这里有没有可行的方法来完成我想做的事情?属性对象位于类上,而您的基类使用数据作为实例属性。通过使其成为子类中的属性,对self.data
的任何和所有访问现在都将处理该属性,即使在基类上定义的方法中也是如此。由于super()
仅在特定父类上寻址属性(包括描述符),super()。数据将失败;基类上没有此类类属性
这意味着这条线
self.data = {}
将触发您的数据
属性设置程序,该设置程序尝试解决不存在的父类上的类属性。请注意,即使它确实存在,也不能将其指定给super()
绑定对象super()
只支持描述符上的\uuuuuuuuuuuuuuuuuuuuuuuu
方法,不支持\uuuuuuuuuuuuuuuuu
或\uuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuu;因此,super()
每次读访问都会触发getter,所以
for x in range(10):
self.data[x] = x * x
将每次调用getter,返回结果,然后分配给结果字典中的键。因为你的getter每次都会创建一个新字典,所以这个任务就完全丢失了;dict理解的结果不会在其他任何地方引用,因此在分配键值对之后,字典将被垃圾收集、更改和所有更改
您需要将该字典的存储重定向到新的实例属性,并对字典进行适当的修改(以便始终保留引用):
因此,现在属性使用实例属性\u data
。赋值给self.data
将触发setter,setter将从值生成的新字典重定向到self.data
。getter删除不需要的键,保留同一个dictionary对象,以便对它的任何其他引用仍然有效,并且将新值分配给键将在正确的位置结束
过滤使用与关键点上的设置交点;这将生成一个新的集合,因此循环仅对实际存在于这两个集合中的键进行迭代。属性对象位于类上,而基类使用数据作为实例属性。通过使其成为子类中的属性,对self.data
的任何和所有访问现在都将处理该属性,即使在基类上定义的方法中也是如此。由于super()
仅在特定父类上寻址属性(包括描述符),super()。数据将失败;基类上没有此类类属性
这意味着这条线
self.data = {}
将触发您的数据
属性设置程序,该设置程序尝试解决不存在的父类上的类属性。请注意,即使它确实存在,也不能将其指定给super()
绑定对象super()
只支持描述符上的\uuuuuuuuuuuuuuuuuuuuuuuu
方法,不支持\uuuuuuuuuuuuuuuuu
或\uuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuu;因此,super()
每次读访问都会触发getter,所以
for x in range(10):
self.data[x] = x * x
将每次调用getter,返回结果,然后分配给结果字典中的键。因为你的getter每次都会创建一个新字典,所以这个任务就完全丢失了;dict理解的结果不会在其他任何地方引用,因此在分配键值对之后,字典将被垃圾收集、更改和所有更改
您需要将该字典的存储重定向到新的实例属性,并对字典进行适当的修改(以便始终保留引用):
因此,现在属性使用实例属性\u data
。赋值给self.data
将触发setter,setter将从值生成的新字典重定向到self.data
。getter删除不需要的键,保留同一个dictionary对象,以便对它的任何其他引用仍然有效,并且将新值分配给键将在正确的位置结束
过滤使用与关键点上的设置交点;这将生成一个新的集合,因此循环仅对两个中实际存在的键进行迭代。我不明白您试图使用super().data=value
…我认为,与其使用super().data
,不如创建一个私有变量:self.\u data
in