我在数据模型层次结构的基类中实现__deepcopy__()
方法。通过对原始copy.deepcopy()
的值调用__dict__
并将它们分配给适当的键来复制原始对象的属性。在传统的用法下(也就是说,没有人去过并直接将复杂对象直接添加到原始对象的__dict__
属性中),这些关键值是否总是字符串,因此不需要深入 - 复制了吗?
例如,在以下代码中:
def __deepcopy__(self, memo=None):
if memo is None:
memo = {}
try:
o = memo[id(self)]
except KeyError:
o = type(self).__new__(self.__class__)
memo[id(self)] = o
for k in self.__dict__:
# o.__dict__[copy.deepcopy(k, memo)] = copy.deepcopy(self.__dict__[k], memo)
o.__dict__[k] = copy.deepcopy(self.__dict__[k], memo)
return o
当前行:
o.__dict__[k] = copy.deepcopy(self.__dict__[k], memo)
假设__dict__
符号表中的键是简单字符串(或不需要特殊处理的其他类型的对象)。
我应该使用:
o.__dict__[copy.deepcopy(k, memo)] = copy.deepcopy(self.__dict__[k], memo)
相反,它允许符号表中的键本身更复杂或更丰富的对象?
答案 0 :(得分:2)
我相信答案是肯定的。课程The documentation表示:
类具有由字典对象实现的命名空间。类属性引用被转换为此字典中的查找,例如,
C.x
已转换为C.__dict__["x"]
这似乎表明,如果你只使用普通的属性赋值,你将总是得到字符串键。 (下面关于实例的部分不是那么明确,但也指的是一个“属性字典”,它显然意味着与类相同。)
当然,正如你在问题中提到的那样,人们可以做一些奇怪的事情,但如果你假设除了正常__dict__
之外没有任何东西被添加到obj.attr = value
,那么你应该没事。
答案 1 :(得分:1)
虽然可以将非字符串键添加到对象的__dict__
(见下文),但毫无疑问,更简单的代码版本可以正常工作。我从来没有遇到任何人在对象的__dict__
中使用非字符串键。
如果有人做了一些违反这个假设并且让你的代码破坏的奇怪事情,那就是他们的错。我声称你的代码仍然是正确和有效的,尽管在这些奇怪的情况下打破了。
这是一种可以将非字符串键添加到对象的dict的方法:
obj.__dict__.update({ object(): 666 })
obj.__dict__
=> {<object at 0x1002b1450>: 666}