【问题标题】:NumPy array change in a function [duplicate]函数中的NumPy数组更改[重复]
【发布时间】:2020-09-28 15:27:09
【问题描述】:

以下代码

def change(in_array):

    in_array += 1             # line a

    in_array = in_array + 1   # line b


x = np.array([1, 2, 3])
change(x)
print(x)

打印[2 3 4]。为什么会这样(为什么 a 和 b 两条线不同)?您能否建议其他修改 NumPy 数组的方法,如第 a 行中所做的那样?一种方法是in_array[:] = in_array + 1;在in_array[:] = ...的情况下,传入数组的值是否总是会改变?

【问题讨论】:

标签: python python-3.x list numpy


【解决方案1】:

让我们看下一段代码:

Try it online!

import numpy as np

def change(in_array, variant = 0):
    if variant == 0:
        in_array += 1             # line a
    elif variant == 1:
        in_array = in_array + 1   # line b
    elif variant == 2:
        in_array[:] = in_array + 1
    elif variant == 3:
        np.put(in_array, np.arange(in_array.size), in_array + 1)
    elif variant == 4:
        np.copyto(in_array, in_array + 1)
    elif variant == 5:
        np.place(in_array, np.ones_like(in_array), in_array + 1)
    else:
        assert False, variant
    print('after, inside', in_array)

orig = np.array([1, 2, 3])
for variant in [0, 1, 2, 3, 4, 5]:
    print('variant', variant)
    x = np.copy(orig)
    print('before', x)
    change(x, variant)
    print('after, outside', x, ('changed', 'not changed')[bool(np.all(x == orig))])

它输出:

variant 0
before [1 2 3]
after, inside [2 3 4]
after, outside [2 3 4] changed
variant 1
before [1 2 3]
after, inside [2 3 4]
after, outside [1 2 3] not changed
variant 2
before [1 2 3]
after, inside [2 3 4]
after, outside [2 3 4] changed
variant 3
before [1 2 3]
after, inside [2 3 4]
after, outside [2 3 4] changed
variant 4
before [1 2 3]
after, inside [2 3 4]
after, outside [2 3 4] changed
variant 5
before [1 2 3]
after, inside [2 3 4]
after, outside [2 3 4] changed

您可能会看到变体 0 在内外回答后给出正确的答案。而变体 1 仅在内部给出正确的。

这是因为变体 0 修改了函数中提供的实际给定数组。虽然变体 1 在函数内部创建了一个修改后的副本,该副本仅保留在函数内部,但实际传递的参数没有被修改。

所以变体 0 修改了传递的参数,而变体 1 修改了传递参数的副本。

在 Python 代码中,函数内部的 a = a + 1 实际上会在函数中创建变量 a 的副本。并且这个局部变量只保留到函数结束,并在函数运行结束时被删除。

变体2,a[:]创建原始数组的视图,它就像对原始数组元素子集的引用,只是:是整个数组的视图,分配给这个视图会修改原始数组。可修改视图也由 a[1:3] 之类的切片和 a[2]a[[1,2]] 之类的索引创建。

a[:] = some_operation(a) 可能是最直观、最快捷的将a 的修改/转换副本分配回a 的方法。

变体 3、4、5 是将右侧表达式分配回数组 a 的其他奇特方式。

【讨论】:

    猜你喜欢
    • 2011-11-23
    • 1970-01-01
    • 2020-07-11
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-02-18
    • 2021-09-24
    • 2017-03-04
    相关资源
    最近更新 更多