【问题标题】:Custom deep copy implementation自定义深拷贝实现
【发布时间】:2015-06-12 15:56:22
【问题描述】:

我正在尝试复制copy.deepcopy 的行为。我有一个行为非常奇怪的方法。

def ReplicateIterable(i):
    try:
        if len(i) > 1:
            return [ReplicateIterable(e) for e in i]
        else:
            return i
    except TypeError:
        return i

这是我的功能。 try 块用于捕获不可迭代的对象。我遇到了一些无限递归问题,因为字符串是可迭代的,并且我使用字符作为列表的元素,因此它会在递归之前检查可迭代长度是否为 >1

我在测试用例中得到了这种行为:

>>> State = [['a', 'b', 'b', 'b', 'c', 'c', 'c'], []]
>>> TempState = ReplicateIterable(State)
>>> TempState
[['a', 'b', 'b', 'b', 'c', 'c', 'c'], []]
>>> TempState[0].remove('c')
>>> TempState[1].append('c')
>>> State
[['a', 'b', 'b', 'b', 'c', 'c', 'c'], ['c']]
>>> TempState
[['a', 'b', 'b', 'b', 'c', 'c'], ['c']]

显然,TempState[0]指向State[0],但TempState[1]确实指向到State[1]State[0]TempState[0].remove('c') 操作保持不变,但State[1]TempState[1] 都被TempState[1].append('c') 修改。

为什么会出现这种情况?如何预防?

【问题讨论】:

    标签: python python-3.x recursion copy iterable


    【解决方案1】:

    问题是任何短于两个项目的列表在您的 ReplicateIterable 函数中都是特殊情况,因此在这些情况下不会创建新对象:

    >>> l1 = [[], [0], [1, 2]]
    >>> l2 = ReplicateIterable(l1)
    >>> [i1 is i2 for i1, i2 in zip(l1, l2)]
    [True, True, False]
    

    您在问题中的 cmets 表明这是一种避免字符串递归问题的尝试,但这不是一种合适的方法。相反,特别是特殊情况的字符串:

    def replicate_iterable(iter):  # note style guide compliance
        """Deep copy the iterable."""
        if isinstance(iter, str):
            return iter
        try:
            return [replicate_iterable(item) for item in iter]
        except TypeError:
            return iter
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2016-12-03
      • 2015-08-23
      • 2013-03-19
      • 1970-01-01
      • 2012-04-12
      • 2015-01-13
      • 2011-09-05
      相关资源
      最近更新 更多