gpt4 book ai didi

python - 为什么 UserDict 的 __copy__ 和 copy() 的行为不一致

转载 作者:太空宇宙 更新时间:2023-11-03 11:37:17 24 4
gpt4 key购买 nike

UserDict Source Code

UserDict 有__copy__ 和.copy() 方法。前者由copy.copy(x) 触发,后者由x.copy() 触发。在 copy() 中,它首先将 self.data 设置为 {},最后使用 c.update(self)填写c.data。但是, update() 将触发 __setitem__ ,可能使 c.data 不同于 self.data

from collections import UserDict
class Foo(UserDict):
def __setitem__(self, key, value):
if isinstance(key, int):
self.data[key] = value
a = Foo({1:2})
# we force it to set key of str type
a.data['3'] = 4
# two different ways to copy
from copy import copy
b = copy(a)
c = a.copy()
# this copy(a) works fine, but a.copy() is not what we expected!!!
assert b == a
assert not c == a

为什么会存在这种不一致?为什么不只是这个:

    def copy(self):
if self.__class__ is UserDict:
return UserDict(self.data.copy())
import copy
return copy.copy(self)

我不知道您可以在 Python3 中直接对 dict 进行子类化。请参阅:How to "perfectly" override a dict? Advantages of UserDict class in Python .无论如何,也许没有理由再为 UserDict 烦恼了。

请参阅提到的网站 Trey Hunner:https://treyhunner.com/2019/04/why-you-shouldnt-inherit-from-list-and-dict-in-python/

最佳答案

UserDict.__copy__UserDict.copy() 之间的预期区别由您链接的源代码中的注释解释。来自 UserDict.__copy__ :

# Create a copy and avoid triggering descriptors

该类的开发人员已确保 __copy__ 不会触发 descriptors .所以 UserDict.copy() 是触发描述符的补充方法。这是通过创建空字典的副本并将所有元素重新插入该副本来实现的。

请注意,UserDict 类很早就引入了,before Python 2.2 ,作为子类化字典的一种方式。当您实现一个旨在由技能水平不可预测的开发人员子类化的类时,您会采取预防措施让类实例以合理的方式运行,即使子类编写得不好。将副本创建为空字典并重新插入元素对我来说就像是一种安全编程。

另一种方法可能是按照您的建议从 .copy() 调用 .__copy__(),并写入子类应覆盖 的文档.copy() 触发描述符。但是,有多少子类开发人员会阅读文档的那部分内容、理解其含义、花时间重写该方法而不在其实现中引入错误?

关于python - 为什么 UserDict 的 __copy__ 和 copy() 的行为不一致,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/56621321/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com