math.exp
和numpy.exp
之间的区别之一是,如果您有一个自定义类C
,它有一个C.exp
方法,numpy.exp
会注意到并委托给这个方法,而math.exp
不会:
class C:
def exp(self):
return 'hey!'
import math
math.exp(C()) # raises TypeError
import numpy
numpy.exp(C()) # evaluates to 'hey!'
然而,如果您查看numpy.exp
的web文档,这似乎是理所当然的。任何地方都没有明确说明。是否有记录该功能的地方?
更普遍地说,是否有一个地方列出了numpy识别的所有这样的方法?
这不是np.exp
函数的特殊行为;这只是如何评估对象dtype数组的结果。
np.exp
和许多numpy函数一样,试图在执行操作之前将非数组输入转换为数组。
In [227]: class C:
...: def exp(self):
...: return 'hey!'
...:
In [228]: np.exp(C())
Out[228]: 'hey!'
In [229]: np.array(C())
Out[229]: array(<__main__.C object at 0x7feb7154fa58>, dtype=object)
In [230]: np.exp(np.array(C()))
Out[230]: 'hey!'
因此,C()
被转换成一个数组,它是一个对象dtype*(C()
不像[1,2,3]
那样是可迭代的(。通常,如果给定对象dtype数组,numpy函数会对元素进行迭代,要求每个元素执行相应的方法。这就解释了[228]最终是如何评估C().exp()
的。
In [231]: np.exp([C(),C()])
Out[231]: array(['hey!', 'hey!'], dtype=object)
In [232]: np.exp([C(),C(),2])
---------------------------------------------------------------------------
AttributeError Traceback (most recent call last)
<ipython-input-232-5010b59d525d> in <module>()
----> 1 np.exp([C(),C(),2])
AttributeError: 'int' object has no attribute 'exp'
如果所有元素都具有CCD_ 15方法,则CCD_。整数不会。ndarray
也没有。
In [233]: np.exp([C(),C(),np.array(2)])
AttributeError: 'numpy.ndarray' object has no attribute 'exp'
math.exp
需要一个数字、一个Python标量(或者可以转换为标量的东西,如np.array(3)
我希望这种行为在所有ufunc
中都是常见的。我不知道还有哪些numpy函数不遵循该协议。
在某些情况下,ufunc
委托给__
方法:
In [242]: class C:
...: def exp(self):
...: return 'hey!'
...: def __abs__(self):
...: return 'HEY'
...: def __add__(self, other):
...: return 'heyhey'
...:
In [243]:
In [243]: np.abs(C())
Out[243]: 'HEY'
In [244]: np.add(C(),C())
Out[244]: 'heyhey'