【问题标题】:Python: Numpy __deepcopy__ TypeErrorPython:Numpy __deepcopy__ 类型错误
【发布时间】:2017-08-08 08:23:04
【问题描述】:

我正在尝试在 ndarray 上使用 deepcopy,该行如下所示:

foo = myArray.__deepcopy__()

我明白了:

TypeError: function takes exactly 1 argument (0 given)

我需要一个深层副本,但我无法导入副本。

【问题讨论】:

  • “我无法导入副本” - 为什么不呢?
  • 除非您使用对象数组(不应该这样做),否则myArray.copy() 应该可以正常工作。

标签: python numpy multidimensional-array copy


【解决方案1】:

copy module 包含__deepcopy__ 的文档,很清楚参数应该是什么:

为了让一个类定义自己的拷贝实现,它可以定义特殊方法__copy__()__deepcopy__()。前者被调用来实现浅拷贝操作;没有传递额外的参数。后者被调用来实现深拷贝操作; 传递一个参数,即备忘录字典。

但是,如果您没有实现自定义的深度可复制类,您通常不需要为此烦恼,只需使用copy.deepcopy

from copy import deepcopy
import numpy as np
arr = np.random.random((100, 100))
deepcopy(arr)

它会在没有您干预的情况下处理memo-dict。注意:大多数__*__ 都是这样设计的,您通常不会也不应该直接调用它们。所以就像你使用x in y 而不是y.__contains__(x) 你通常使用copy.deepcopy(x) 而不是x.__deepcopy__(dict())

【讨论】:

    【解决方案2】:

    copy中的相关代码为:

    def deepcopy(x, memo=None, _nil=[]):
        """Deep copy operation on arbitrary Python objects.
    
        See the module's __doc__ string for more info.
        """
    
        if memo is None:
            memo = {}
            ....
               copier = getattr(x, "__deepcopy__", None)
                if copier:
                    y = copier(memo)
    ...
    # If is its own copy, don't memoize.
    if y is not x:
        memo[d] = y
        _keep_alive(x, memo) # Make sure x lives at least as long as d
    return y
    

    所以memo 是一个memoize 字典,至少在“正确”使用时是这样

    所以如果我将字典传递为memo,它会改变:

    In [160]: dd={}
    In [161]: A2=copy.deepcopy(A,memo=dd)
    In [162]: dd
    Out[162]: 
    {2814755008: array([[[0, 1, 0, 0, 0, 0],
             [0, 0, 1, 0, 0, 1],
             [0, 0, 0, 1, 0, 1],
             [1, 0, 0, 0, 1, 0]],
    
            [[0, 0, 1, 0, 0, 0],
             [0, 0, 1, 1, 0, 0],
             [0, 0, 0, 0, 0, 0],
             [0, 0, 0, 0, 0, 0]]]), 2814808588: [array([[[0, 1, 0, 0, 0, 0],
              [0, 0, 1, 0, 0, 1],
              [0, 0, 0, 1, 0, 1],
              [1, 0, 0, 0, 1, 0]],
    
             [[0, 0, 1, 0, 0, 0],
              [0, 0, 1, 1, 0, 0],
              [0, 0, 0, 0, 0, 0],
              [0, 0, 0, 0, 0, 0]]])]}
    In [163]: id(A)
    Out[163]: 2814755008
    In [167]: id(dd[id(A)])
    Out[167]: 2814568472
    In [168]: id(A2)
    Out[168]: 2814568472
    

    memo 保留副本的记录。我不知道第二项是什么。

    如果我要求另一个具有相同备忘录的深层副本,它会给出已记忆的数组而不是新副本。

    In [173]: A3=copy.deepcopy(A,memo=dd)
    In [174]: id(A2)
    Out[174]: 2814568472
    In [175]: id(A3)
    Out[175]: 2814568472
    

    如果数组是对象 dtype,deepcopy 可能会有所不同。备忘录看起来确实不一样。

    【讨论】:

      【解决方案3】:

      特殊的__deepcopy__ 方法采用memo 参数。您可以为此传递一个空字典:

      foo = myArray.__deepcopy__({})
      

      【讨论】:

      • 奇怪,我在文档中没有看到,但它有效。谢谢!
      • 备忘录什么时候可以成为一个元组?文档说这是一个字典。
      • @user2357112 我也自然会说dict,但是numpy doc使用了一个元组作为样本:docs.scipy.org/doc/numpy/reference/…
      • @MosesKoledoye:这对我来说似乎是一个格式问题,而不是示例输入。这不是唯一的格式问题。几行之后,我们有 ndarray.__new__((S, ...),括号不匹配。
      • @user2357112 你是对的,但我特别惊讶为什么它几乎适用于任何容器类型
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2023-03-13
      • 1970-01-01
      • 2016-07-02
      • 2021-06-11
      • 1970-01-01
      • 2019-06-10
      • 2020-08-07
      相关资源
      最近更新 更多