Почему встроенные функции, такие как abs, работают в массиве numpy?
Я очень удивлен тем, что abs
работает в массиве numpy, но не в списках. Почему это?
import numpy as np
abs(np.array((1,-2)))
array([1, 2])
abs([1,-1])
TypeError: bad operand type for abs(): 'list'
Кроме того, встроенные функции, такие как sum
, также работают с массивом numpy. Думаю, это потому, что массив numpy поддерживает __getitem__
? Но в случае abs
, если он зависит от __getitem__
, он должен работать и для списка, но это не так.
Ответы
Ответ 1
Это потому, что numpy.ndarray
реализует метод __abs__(self)
. Просто предоставьте его для своего собственного класса, и abs()
будет волшебным образом работать. Для не встроенных типов вы также можете предоставить это средство после факта. Например.
class A:
"A class without __abs__ defined"
def __init__(self, v):
self.v = v
def A_abs(a):
"An 'extension' method that will be added to `A`"
return abs(a.v)
# Make abs() work with an instance of A
A.__abs__ = A_abs
Однако это не будет работать для встроенных типов, таких как list
или dict
.
Ответ 2
abs
функция ищет метод __abs__
.
вы также можете, подобно numpy, реализовать метод __abs__
в своих классах, поэтому abs будет работать с ними.
то есть.
class A(object):
def __abs__(self):
return 8
>>> a= A()
>>> abs(a)
8
>>>
Ответ 3
sum
работает с итерабельными, такими как массивы списка или numpy.
abs
работает с значениями, которые определяют метод __abs__
, например числа или numpy.arrays:
>>> x = -1
>>> x.__abs__()
1
>>> class A(object):
... def __abs__(self):
... return 12
>>> a = A()
>>> abs(a)
12
list
не определяют этот метод, хотя вы можете использовать понимание карт или списков (map(abs, [1, -1])
и [abs(x) for x in [1,-1]]
соответственно) для того, что вам нужно. Если вам нравится overkill, вы также можете выбрать список подкласса и определить numpy-like __abs__
(но, как правило, это понимание является более предпочтительным)