在numpy python中使用frompyfunc创建的ufunc如果省略了带有默认值的参数将无法工作

svujldwt  于 12个月前  发布在  Python
关注(0)|答案(1)|浏览(104)

我在python中做了一个简单的函数,现在我想用它来处理numpy数组。该函数有一个带有默认值的参数,因此通常可以省略。但是,当使用frompyfunc时,省略默认参数将不起作用。为什么?原始函数如何与numpy.arrays一起使用?

import numpy as np.array

# define a simple f with 2 args, one of them defaults to 1
def my_func(x, y=1):
    return x + y

# create ufunc to work with arrays
# refer to original my_func, declare 2 inputs (x and y), 1 output (x + y)
my_ufunc = np.frompyfunc(my_func, 2, 1)

# Call the ufunc with 2 arguments (all will work)
print(my_ufunc([1, 2, 3], 1))
print(my_ufunc([1, 2, 3], [1]))
print(my_ufunc([1, 2, 3], [1, 2, 3]))

# Call the ufunc with 1 positional argument, omit the 2nd for which a default
# value was previously defined
# but it will not work :(
print(my_ufunc([1, 2, 3]))

字符串
TRACEBACK:TypeError:my_func(vectorized)()接受2到3个位置参数,但给出了1个

fivyi3re

fivyi3re1#

numpy已经重载了numpy数组上的所有算术运算符(+,-,*,/等),你只需要将list转换为numpy数组来使用这些运算符。

import numpy as np

def my_func(x, y=1):
    return x + y

lst1 = [1,2,3]
arr1 = np.array(lst1)  # convert list to numpy array
arr2 = np.array([3,4,5])  # define and convert list to numpy array
print(my_func(arr1, arr2))
print(my_func(arr1))

个字符
你可以查看numpy quickstart和numpy broadcasting,了解numpy如何覆盖很多操作。
至于你的主要问题,np.frompyfunc创建了一个 Package 器函数,它只检查和复制参数的数量,但不检查默认参数,但你不需要/不应该使用它,因为它比使用numpy的重载运算符慢得多(也长得多)。

编辑:一个支持默认参数的np.frompyfunc的实现如下所示,这是未优化的,缺乏大量的错误检查和处理仅位置参数的能力,我必须引用Get a function argument's default value?

import numpy as np
import functools
import inspect

def get_default_args(func):
    signature = inspect.signature(func)
    return {
        k: v.default
        for k, v in signature.parameters.items()
    }

def numpyfrompyfunc(func):
    default_args = get_default_args(func)
    @functools.wraps(func)
    def wrapper(*args,**kwargs):
        new_kwargs = {}
        for i, (key,value) in enumerate(default_args.items()):
            if i < len(args):
                new_kwargs[key] = args[i]
            else:
                if key in kwargs:
                    new_kwargs[key] = value
                elif value is not inspect.Parameter.empty:
                    new_kwargs[key] = default_args[key]
                else:
                    raise ValueError(f"parameter {key} unfilled")
        max_length = 0
        kwarg_sizes = {}
        for key,value in new_kwargs.items():
            if hasattr(value, "__len__"):
                max_length = max(max_length, len(value))
                kwarg_sizes[key] = len(value)
            else:
                kwarg_sizes[key] = 1
        outputs = []
        for i in range(max_length):
            kwargs_single = {}
            for key,value in new_kwargs.items():
                if kwarg_sizes[key] == 1:
                    kwargs_single[key] = value
                else:
                    kwargs_single[key] = value[i]
            outputs.append(func(**kwargs_single))
        return np.array(outputs)
    return wrapper

def my_func(x, y=1):
    return x + y

new_func = numpyfrompyfunc(my_func)
lst1 = [1,2,3]
lst2 = [3,4,5]
print(new_func(lst1 , lst2 ))
print(new_func(lst1 ))

相关问题