为什么 np.ndarray.__deepcopy__ 需要多余的参数?

Why does np.ndarray.__deepcopy__ require a superfluous argument?

副本会回答 what,但不会充分回答 why 或者为什么文档中没有提到它,即使它是必需的。继续阅读更多...


有两种方法可以对 numpy 数组进行深拷贝。一种方法是使用 copy 模块中的 copy.deepcopy。另一种方法是直接调用array.__deepcopy__

来自docs

ndarray.__deepcopy__() → Deep copy of array.

Used if copy.deepcopy is called on an array.

文档提示调用此函数的正确方法是不带任何参数。然而....

In [47]: x
Out[47]: 
array([[1, 1],
       [2, 2]])

In [48]: x.__deepcopy__()
---------------------------------------------------------------------------
TypeError                                 Traceback (most recent call last)
<ipython-input-48-00c3b8eda618> in <module>()
----> 1 x.__deepcopy__()

TypeError: __deepcopy__() takes exactly 1 argument (0 given)

返回一个TypeError!但是...

In [51]: x.__deepcopy__(None)
Out[51]: 
array([[1, 1],
       [2, 2]])

甚至...

In [52]: x.__deepcopy__([12345, 'blah blah'])
Out[52]: 
array([[1, 1],
       [2, 2]])

看来此函数需要一个参数,但据推测该参数与返回的副本无关。

文档中没有提到这个参数。这是一个文档错误吗?怎么连忽略都传进去了?

Python 要求 __deepcopy__() 方法接受一个参数 memo (docs):

In order for a class to define its own copy implementation, it can define special methods __copy__() and __deepcopy__(). The former is called to implement the shallow copy operation; no additional arguments are passed. The latter is called to implement the deep copy operation; it is passed one argument, the memo dictionary. If the __deepcopy__() implementation needs to make a deep copy of a component, it should call the deepcopy() function with the component as first argument and the memo dictionary as second argument.

它的目的是

keeping a “memo” dictionary of objects already copied during the current copying pass

如果对象包含引用循环,这可以防止在复制过程中出现递归循环。

我猜 numpy 不需要使用该参数,因为数组通常不包含对其他 Python 对象的递归引用,因此它被简单地忽略了。