矢量化函数无法求值



我遇到了矢量化函数的问题:

def func(y):
return sum(x**(-y) for x in range(1, 10))
vect_func = np.vectorize(func)
vect_func([1, 2, 3, 4, 5])
# Output:
# ValueError: Integers to negative integer powers are not allowed.

而下面的操作很好:

[func(t) for t in [1, 2, 3, 4, 5]]
# Output:
# [2.8289682539682537, 1.5397677311665408, 1.1965319856741932, 1.0819365834937567, 1.0368973413446938]

有可能让np.vectorize处理这个例子吗?

当函数在np.vectorize中不起作用时,最好验证参数是什么。

让我们为函数添加一个type打印:

In [36]: def func(y):
...:     print(type(y))
...:     return sum(x**(-y) for x in range(1, 10))
...: 

在列表理解中,Pythonint被传递:

In [37]: func(3)
<class 'int'>
Out[37]: 1.1965319856741932

使用vectorized版本:

In [40]: vect_func(3)
<class 'numpy.int64'>
Traceback (most recent call last):
File "<ipython-input-40-65e2816d8003>", line 1, in <module>
vect_func(3)
File "/usr/local/lib/python3.8/dist-packages/numpy/lib/function_base.py", line 2163, in __call__
return self._vectorize_call(func=func, args=vargs)
File "/usr/local/lib/python3.8/dist-packages/numpy/lib/function_base.py", line 2241, in _vectorize_call
ufunc, otypes = self._get_ufunc_and_otypes(func=func, args=args)
File "/usr/local/lib/python3.8/dist-packages/numpy/lib/function_base.py", line 2201, in _get_ufunc_and_otypes
outputs = func(*inputs)
File "<ipython-input-36-311d525a60ba>", line 3, in func
return sum(x**(-y) for x in range(1, 10))
File "<ipython-input-36-311d525a60ba>", line 3, in <genexpr>
return sum(x**(-y) for x in range(1, 10))
ValueError: Integers to negative integer powers are not allowed.

y不是pythonint,它是numpy内部

In [41]: func(np.int64(3))
<class 'numpy.int64'>
Traceback (most recent call last):
File "<ipython-input-41-c34830937ffd>", line 1, in <module>
func(np.int64(3))
File "<ipython-input-36-311d525a60ba>", line 3, in func
return sum(x**(-y) for x in range(1, 10))
File "<ipython-input-36-311d525a60ba>", line 3, in <genexpr>
return sum(x**(-y) for x in range(1, 10))
ValueError: Integers to negative integer powers are not allowed.

如果我们故意通过Pythonint,它会起作用:

In [42]: vect_func(np.array([1,2,3], object))
<class 'int'>
<class 'int'>
<class 'int'>
<class 'int'>
Out[42]: array([2.82896825, 1.53976773, 1.19653199])

当将几个数组传递给标量函数时,np.vectorize非常方便,并且您希望利用broadcasting。但对于一个列表,或者可以压缩的列表,它不会给列表的理解增加任何东西,甚至不会提高速度。

正如本例所示,它有一些陷阱,无法抓住新手(甚至更有经验的用户(。这是输入的性质。对于许多其他SO问题,这是返回值(自动otypes(的性质。

最新更新