我正在编写从Python类dictcollections.Counter继承的定制类,并且我面临着deepcopy的行为问题.问题在于,从dict继承而不是从Counter继承时,deepcopy基本上可以正常工作.

下面是一个例子:

from copy import deepcopy
from collections import Counter

class MyCounter(Counter):
    def __init__(self, foo):
        self.foo = foo

class MyDict(dict):
    def __init__(self, foo):
        self.foo = foo


c = MyCounter(0)
assert c.foo == 0  # Success
c1 = deepcopy(c)
assert c1.foo == 0  # Failure


d = MyDict(0)
assert d.foo == 0  # Success
d1 = deepcopy(d)
assert d1.foo == 0  # Success

我有点不明白为什么会发生这种情况,因为Counter类的源代码似乎没有改变深度副本的任何内容(例如,没有定制__deepcopy__方法).

我知道我可能必须编写一个定制的__deepcopy__方法,但我不清楚如何编写.总体而言,我宁愿不必这样做,因为它在dict上运行得很好.

任何帮助都将不胜感激.

推荐答案

deepcopy有几个后备方案,在答案here中已有说明

在本例中,您的特定基类Counter专门化了Pickle序列化,这是deepcopy将采用的(作为第二种 Select ,因为碰巧不存在__deepcopy__的专门化).

如果您在调试器中遍历代码,您会发现它以计数器的__reduce__方法结束,其中Counter的python3.9实现具有:

    def __reduce__(self):
        return self.__class__, (dict(self),)

我们看到的地方可以看到信息丢失的地方,因为Counter‘S在这里的实现依赖于除了字典部分本身之外,没有任何其他字段存储在这个对象中.

你可以重载__reduce____reduce_ex__,这将修复酸洗,作为额外的好处,你也可以重载__deepcopy__并为它提供必要的实现.

实现我们自己的深度副本并不复杂,我们可以保持代码非常简单:

class MyCounter(Counter):
    def __init__(self, foo):
        self.foo = foo
        
    def __deepcopy__(self, memo):
        copy_instance = MyCounter(deepcopy(self.foo, memo))
        for key, val in self.items():
            copy_instance[deepcopy(key, memo)] = val  # val is just an int
        return copy_instance

c = MyCounter(123)
c['deep'] = 1
c['copy'] = 2

c1 = deepcopy(c)
assert c1.foo == c.foo
assert c1['deep'] == c['deep']
assert c1['copy'] == c['copy']

(在大多数情况下,我可能会建议不要重载计数器或DICT,以便向它们添加更多属性,而是编写一个定制类,将计数器或DICT实例变量设置为has.)

Python-3.x相关问答推荐

使用Pandas 阅读Excel定义的名称和单元格值(&Q;)

Numpy argmin()以查找最近的元组

如何检索与美汤相似的标签中的文本?

被多个\n拆分并保留

PYSMB中的进度条

按一列分组,如果日期列相同,则在数字列中填写缺少的值

添加任意数量的 pandas 数据框

如果集合大于 len(x),则 pandas 在重复的行中拆分集合列

Pandas:从 Pandas 数据框中的 1 和 0 模式中获取值和 ID 的计数

过滤并获取数据框中条件之间的行

如何在python中将列表转换为其他格式

对齐文本文件中的列

类型提示和链式赋值以及多重赋值

活动屏幕上的 PyQt4 中心窗口

为什么 Django South 1.0 使用 iteritems()?

Python 错误:IndexError:字符串索引超出范围

Python 3.5:async with导致 SyntaxError.为什么?

是否在未完成初始化的对象上调用了 del?

在 Ubuntu 上为 Python3 安装 mod_wsgi

如何为 anaconda python3 安装 gi 模块?