python函数在调用scop时修改变量

2024-09-27 22:23:16 发布

您现在位置:Python中文网/ 问答频道 /正文

有人能解释为什么fun1不修改变量y的值,而fun2修改吗?我需要逐行修改数组,但同时更新y并不是我想要的行为。你知道吗

def fun1(x):
    x = 2*x
    return x


def fun2(x):
    for i in range(0, x.shape[0]):
        x[i, :] = 2*x[i, :]
    return x


y = np.random.uniform(0, 100, (10, 10))

z1 = fun1(y)
print(np.array(z1 == y).all())
# False

z2 = fun2(y)
print(np.array(z2 == y).all())
# True

Tags: inforreturndefnprange数组all
3条回答

修改函数以显示对象的id

def fun1(x):
    print(id(x),id(y))
    x = 2*x
    print(id(x))
    return x

In [315]: y = np.arange(3)
In [316]: id(y)
Out[316]: 140296824014768
In [317]: z = fun1(y)
140296824014768 140296824014768    
140296823720096
In [318]: id(z)
Out[318]: 140296823720096

因此y引用的数组被传递给函数,并且可以同时被x(参数变量)和y(外部变量)引用。但是赋值改变了x引用—该对象被传递回zy不变。你知道吗

def fun2(x):
    print(id(x), id(y))
    x[0] = 23
    print(id(x))
    return x

使用第二个函数,赋值会更改x的元素,但不会更改被引用对象的idyxz都引用相同的数组。你知道吗

In [320]: y
Out[320]: array([0, 1, 2])
In [321]: id(y)
Out[321]: 140296824014768
In [322]: z = fun2(y)
140296824014768 140296824014768
140296824014768
In [323]: id(z)
Out[323]: 140296824014768
In [324]: z
Out[324]: array([23,  1,  2])
In [325]: y
Out[325]: array([23,  1,  2])

如果我们在将y传递给函数之前或在函数内部复制它,那么修改x将不会修改y。你知道吗

In [327]: y = np.arange(3)
In [328]: id(y)
Out[328]: 140296823645328
In [329]: z = fun2(y.copy())
140296823647968 140296823645328
140296823647968
In [330]: id(z)
Out[330]: 140296823647968
In [331]: z
Out[331]: array([23,  1,  2])
In [333]: y
Out[333]: array([0, 1, 2])

我们将数组传递给函数的事实并不会改变对副本的需要。我们会得到同样的行为,即使我们只是在顶级执行的行动。你知道吗

In [334]: y = np.arange(3)
In [335]: x = y.copy()
In [336]: x[:2]=22
In [337]: x
Out[337]: array([22, 22,  2])
In [338]: y
Out[338]: array([0, 1, 2])

如果对象是列表,则得到相同的行为:

In [339]: yl = [1,2,3]
In [340]: fun1(yl)
140296925836360 ...
140296824729096
Out[340]: [1, 2, 3, 1, 2, 3]

In [341]: fun2(yl)
140296925836360 ...
140296925836360
Out[341]: [23, 2, 3]
In [343]: yl
Out[343]: [23, 2, 3]

fun1中,执行x = 2*x将变量x重新分配给新数组。 在fun2中,索引赋值x[i, :] = __直接修改原始数组。你知道吗

修改一个对象并保持原稿完整的唯一方法,通常是复制原稿,我认为你在寻找这样的东西:

def fun2(x):
    x = x.copy()
    for i in range(0, x.shape[0]):
        x[i, :] = 2*x[i, :]
    return x

那么,关于fun1和fun2之间的明显区别的问题的答案是,python与大多数OOP语言一样,是通过对象引用传递的。第一个函数重新分配函数签名中声明的变量,但不改变其输入。第二,简单地改变它的输入。要了解更多信息,请看这篇文章https://robertheaton.com/2014/02/09/pythons-pass-by-object-reference-as-explained-by-philip-k-dick/

相关问题 更多 >

    热门问题