有序字典的深层复制是否可以保留其顺序?

时间:2018-07-24 00:09:44

标签: python deep-copy ordereddictionary

我制作了一个小程序,并测试了它是否保持顺序。但是,我仍然想确保TextField会做到这一点。

deepcopy

该程序的输出为

import copy
import collections

a_dict = collections.OrderedDict()
a_dict['m'] = 10
a_dict['u'] = 15
a_dict['c'] = 5
a_dict['h'] = 25
a_dict['a'] = 55
a_dict['s'] = 30

print(a_dict)

other_dict = copy.deepcopy(a_dict)

other_dict['g'] = 75
other_dict['r'] = 35

print(other_dict)

3 个答案:

答案 0 :(得分:4)

通过copy.deepcopy正确实现的复制应产生与原始对象相等的对象(假设完全定义了相等性)。虽然没有,但是没有关于OrderedDictcopy.deepcopy的明确书面保证,特别是如果副本中OrderedDict的顺序更改了,则该保证将不等于原始的OrderedDict ,这将大大违反复制平等的期望。

由于键或值的__deepcopy__方法可能确实做得很糟糕(例如修改源OrderedDict),因此不能真正给予任何保证,但是除了病理情况外,您还可以可以依靠copy.deepcopy来保持顺序。

答案 1 :(得分:1)

在CPython中,似乎保留了顺序。我通过检查deepcopy的实现得出了这个结论。在这种情况下,它将在您的__reduce_ex__对象上找到__reduce__OrderedDict方法以进行酸洗:

https://github.com/python/cpython/blob/master/Lib/copy.py#L159-L161

def deepcopy(x, memo=None, _nil=[]):
...
                    reductor = getattr(x, "__reduce_ex__", None)
                    if reductor is not None:
                        rv = reductor(4)
                    else:
                        reductor = getattr(x, "__reduce__", None)
                        if reductor:
                            rv = reductor()

那些返回odict_iterator的对象用于构造,因此将保留顺序:

>>> a = {}
>>> b = collections.OrderedDict()
>>> a['a'] = 1
>>> b['a'] = 1
>>> a.__reduce_ex__(4)
(<function __newobj__ at 0x10471a158>, (<class 'dict'>,), None, None, <dict_itemiterator object at 0x104b5d958>)
>>> a.__reduce__()
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "/opt/local/Library/Frameworks/Python.framework/Versions/3.6/lib/python3.6/copyreg.py", line 65, in _reduce_ex
    raise TypeError("can't pickle %s objects" % base.__name__)
TypeError: can't pickle dict objects
>>> b.__reduce_ex__(4)
(<class 'collections.OrderedDict'>, (), None, None, <odict_iterator object at 0x104c02d58>)
>>> b.__reduce__()
(<class 'collections.OrderedDict'>, (), None, None, <odict_iterator object at 0x104c5c780>)
>>> 

答案 2 :(得分:0)

对象的深拷贝应返回相同类型的对象。所以作为副本返回的orderdict应该保持有序吗?

编辑-这不是完全正确的答案。请在下面查看Greg的评论。