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