Python ndarray的浅拷贝到函数
如果我有一个列表Python ndarray的浅拷贝到函数,python,numpy,Python,Numpy,如果我有一个列表x=[1,2,3],并将其传递给一个函数f,该函数以f(x[:])的形式使用运算符+=,则生成一个浅层副本,并且内容不变: def f(x): print "f, x = ", x, ", id(x) = ", id(x) x += [1] print "f, x = ", x, ", id(x) = ", id(x) x = [1,2,3] print "x = ", x, ", id(x) = ", id(x) f(x[:]) print "x =
x=[1,2,3]
,并将其传递给一个函数f
,该函数以f(x[:])
的形式使用运算符+=
,则生成一个浅层副本,并且内容不变:
def f(x):
print "f, x = ", x, ", id(x) = ", id(x)
x += [1]
print "f, x = ", x, ", id(x) = ", id(x)
x = [1,2,3]
print "x = ", x, ", id(x) = ", id(x)
f(x[:])
print "x = ", x, ", id(x) = ", id(x)
输出:
x = [1, 2, 3] , id(x) = 139701418688384
f, x = [1, 2, 3] , id(x) = 139701418790136
f, x = [1, 2, 3, 1] , id(x) = 139701418790136
x = [1, 2, 3] , id(x) = 139701418688384
x = [1 2 3] , id(x) = 139701418284416
f, x = [1 2 3] , id(x) = 139701418325856
f, x = [2 3 4] , id(x) = 139701418325856
x = [2 3 4] , id(x) = 139701418284416
然而,对于ndarray
x=np.array([1,2,3])
我期待着相同的行为,我很惊讶内容被更改了,即使确实制作了一个副本:
import numpy as np
def f(x):
print "f, x = ", x, ", id(x) = ", id(x)
x += [1]
print "f, x = ", x, ", id(x) = ", id(x)
x = np.array([1,2,3])
print "x = ", x, ", id(x) = ", id(x)
f(x[:])
print "x = ", x, ", id(x) = ", id(x)
输出:
x = [1, 2, 3] , id(x) = 139701418688384
f, x = [1, 2, 3] , id(x) = 139701418790136
f, x = [1, 2, 3, 1] , id(x) = 139701418790136
x = [1, 2, 3] , id(x) = 139701418688384
x = [1 2 3] , id(x) = 139701418284416
f, x = [1 2 3] , id(x) = 139701418325856
f, x = [2 3 4] , id(x) = 139701418325856
x = [2 3 4] , id(x) = 139701418284416
(我知道+[1]
函数对数据数组和列表的作用是不同的)。如何传递列表中的数据集并避免这种行为
奖金问题为什么在函数f
中使用x=x+[1]
可以解决问题?如果需要副本,可以使用numpy数组的方法:
f(x.copy())
请注意,即使x
和x[:]
的id
不同,这些数组可能共享相同的内存,因此对一个数组的更改将传播到另一个数组,反之亦然:
x = np.array([1,2,3])
y = x[:]
np.may_share_memory(x, y) # True
z = x.copy()
np.may_share_memory(x, z) # False
但是,通常情况下,您不会将副本传递给函数。您将在函数内创建一个副本:
def give_me_a_list(lst):
lst = list(lst) # makes a shallow copy
# ...
def give_me_an_array(arr):
arr = np.array(arr) # makes a copy at least if you don't pass in "copy=False".
# ...
谢谢iPython的内省说,
id
是变量的内存地址,但是……我是否遗漏了什么?另外,我还添加了一个额外的问题——你能帮忙吗?@bcf对于额外的问题,你可能想看看我对另一个问题的回答:。@bcfid
是实例的内存地址。但是numpy数组的实际数组存储为属性(由于ndarray是作为C类实现的,所以有点复杂)。你所得到的是一个视图,它基本上是另一个实例,它与原始内存共享一些/所有内存。@ BCF,它是复杂的,因为这是因为<代码> NoMPy < /Cord>基本上封装了C数组并使之成为面向对象。@ BCF很好,Python与C++(或java,……)不可比。然后NumPy数组就无法与列表进行比较了。至于x=x+1
和x+=1
,这在几乎所有编程语言中都是相似的。