【问题标题】:Python function that acts on provided array作用于提供的数组的 Python 函数
【发布时间】:2022-01-22 10:09:07
【问题描述】:

一些 NumPy 函数(例如 argmaxcumsum)可以将数组作为可选的 out 参数并将结果存储在该数组中。请原谅我在这里对术语的不完美掌握(这使我无法在谷歌上搜索答案),但这些函数似乎以某种方式作用于超出其范围的变量。

我将如何转换这个简单的函数,以便它可以将out 参数作为提到的函数?

import numpy as np

def add_two(a):
    return a + 2

a = np.arange(5)

a = add_two(a)

据我了解,add_two() 的重写版本将允许将上面的最后一行替换为

add_two(a, out=a)

【问题讨论】:

    标签: python numpy scope numpy-ndarray


    【解决方案1】:

    在我看来,最好和最明确的做法就是按照您目前的做法去做。 Python 将值而不是引用作为函数中的参数传递,因此您只能修改可变对象。

    一种方法是:

    import numpy as np
    def add_two(a, out):
        out[:] = a+2
    a = np.arange(5)
    add_two(a, out=a)
    a
    

    输出:

    array([2, 3, 4, 5, 6])
    

    注意。与您当前的解决方案不同,这要求作为参数 out 传递的对象存在并且是一个数组

    【讨论】:

    • Python 只传递引用。它从不按值传递。但是,是的,您只能通过可变性的定义来修改可变对象。
    • @Mad 看起来像是语义问题。检查this answer,引用没有通过,给对象新建一个。这就是我这句话的意思,你不传递名称
    • 很公平。我认为这可以解决问题。
    【解决方案2】:

    天真的解决方案是用计算结果填充输出数组的缓冲区:

    def add_two(a, out=None):
        result = a + 2
        if out is None:
            out = result
        else:
            out[:] = result
        return out
    

    问题(如果你可以这么说的话)是你仍在生成中间数组,并有效地绕过了首先预先分配结果的好处。更细微的方法是使用 numpy 管道中函数的 out 参数:

    def add_two(a, out=None):
        return np.add(a, 2, out=out)
    

    不幸的是,与一般矢量化一样,这只能根据所需的操作集逐个进行。

    顺便说一句,这与范围无关。 Python 对象特别适用于所有命名空间(尽管它们的名称可能不是)。如果在函数中修改了可变参数,则更改将始终在函数外部可见。参见例如"Least Astonishment" and the Mutable Default Argument

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-06-23
      • 2011-07-04
      • 2019-11-16
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多