Python - 为啥通过值传递的 ndarray 在函数外部发生变化? [复制]
Posted
技术标签:
【中文标题】Python - 为啥通过值传递的 ndarray 在函数外部发生变化? [复制]【英文标题】:Python - Why ndarray passed by value changes outside function? [duplicate]Python - 为什么通过值传递的 ndarray 在函数外部发生变化? [复制] 【发布时间】:2017-08-23 05:55:01 【问题描述】:我有以下功能:
def a_function(foo):
bar = foo
print("bar1: ", bar, id(foo))
bar[0] = foo[2]
print("bar2: ", bar, id(foo))
以列表为参数调用:
foo = [0, 1, 2, 3, 4, 5, 6, 7, 8]
print("foo1: ", foo, id(foo))
a_function(foo[:])
print("foo2: ", foo, id(foo))
输出:
foo1: [0, 1, 2, 3, 4, 5, 6, 7, 8] 140118901565768
bar1: [0, 1, 2, 3, 4, 5, 6, 7, 8] 140118901566472
bar2: [2, 1, 2, 3, 4, 5, 6, 7, 8] 140118901566472
foo2: [0, 1, 2, 3, 4, 5, 6, 7, 8] 140118901565768
以ndarray为参数调用:
foo = np.arange(0,9)
print("foo1: ", foo, id(foo))
a_function(foo[:])
print("foo2: ", foo, id(foo))
输出:
foo1: [0 1 2 3 4 5 6 7 8] 139814139381760
bar1: [0 1 2 3 4 5 6 7 8] 139814115258000
bar2: [2 1 2 3 4 5 6 7 8] 139814115258000
foo2: [2 1 2 3 4 5 6 7 8] 139814139381760
我将它作为副本传递 foo[:] 甚至在函数内部再次复制,它也有自己的 id。然而,当 foo2 是一个 ndarray 时,它在函数范围之外改变了它的值。这怎么可能?
【问题讨论】:
阅读上述副本中的 NumPy 答案。它基本上制作了数组的浅拷贝。尝试使用foo.copy()
。
@rayryeng: [:]
为 Python 列表创建一个浅拷贝。对于 numpy 数组,[:]
不会复制,它只会在数组中创建另一个视图。
@J.F.Sebastian 对。我混淆了我的术语。感谢您的澄清。
@rayryeng:注意:不同之处不仅仅是文字。 Modifying a copy may keep the original list intact but modifying an array view changes the original.
【参考方案1】:
首先,你不会通过传递序列的完整切片来传递“按值”,Python 总是通过赋值,即隐式发生的第一件事是foo = argument
当调用你的函数。
现在回答你的实际问题:
创建一个完整的列表切片会创建一个新列表。您正在将原始列表的浅表副本传递给函数。
创建一个 numpy 数组的(完整)切片会在原始数组保存的相同数据(内存中的某处)上生成一个 视图。视图和原始视图共享相同的数据,如果您更改其中一个的内容,则更改在所有视图中都是可见的。
延伸阅读:http://scipy-cookbook.readthedocs.io/items/ViewsVsCopies.html
【讨论】:
我知道 Python 通过赋值传递。我发现这很有帮助:http://***.com/questions/986006/how-do-i-pass-a-variable-by-reference。我刚刚看到我可以通过复制适用于列表的序列“foo [:]”来隐式传递它。但无论如何你是对的。我将不得不阅读 numpy 文档中的视图。谢谢。【参考方案2】:在 Python 中,
bar = foo
不制作副本。 bar
和 foo
引用同一个数组对象。
此操作会复制一个列表,但只是一个数组的view
:
foo[:]
如果要将bar
中的更改与foo
隔离开,则需要使用foo.copy()
。
我建议查看一些基本的 numpy 文档,尤其是关于视图和副本的内容。
【讨论】:
我会读到关于 numpy 中的视图。 foo.copy() 解决了这个问题。谢谢。以上是关于Python - 为啥通过值传递的 ndarray 在函数外部发生变化? [复制]的主要内容,如果未能解决你的问题,请参考以下文章
数据分析2 numpy(ndarray数组,属性,创建,索引切片,运算,函数,随机数), Pandas(Series创建,缺失值处理,特性,索引,DataFrame)