19

I feel surprised that abs works on numpy array but not on lists. Why is that?

import numpy as np

abs(np.array((1,-2)))
array([1, 2])

abs([1,-1])
TypeError: bad operand type for abs(): 'list'

Also, built in functions like sum also works on numpy array. I guess it is because numpy array supports __getitem__? But in case of abs, if it depends on __getitem__ it should work for list as well, but it didn't.

colinfang
  • 20,909
  • 19
  • 90
  • 173

3 Answers3

25

That's because numpy.ndarray implements the __abs__(self) method. Just provide it for your own class, and abs() will magically work. For non-builtin types you can also provide this facility after-the-fact. E.g.

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

However, this will not work for built-in types, such as list or dict.

Michael Wild
  • 24,977
  • 3
  • 43
  • 43
5

abs function looks for __abs__ method.

you can also, like numpy, implement the __abs__ method in your classes so abs would works with them.

i.e.

class A(object):
    def __abs__(self):
        return 8

>>> a= A()
>>> abs(a)
8
>>>
Elisha
  • 4,811
  • 4
  • 30
  • 46
2

sum works on iterables, such as list or numpy arrays.

abs works on values which define an __abs__ method, such as numbers or numpy.arrays:

>>> x = -1
>>> x.__abs__()
1

>>> class A(object):
...     def __abs__(self):
...         return 12
>>> a = A()
>>> abs(a)
12

lists do not define this method, although you can use map or list comprehensions (map(abs, [1, -1]) and [abs(x) for x in [1,-1]] respectively) for what you required. If you like overkill, you can also subclass list and define a numpy-like __abs__ (but the comprehension is generally preferable)

val
  • 8,459
  • 30
  • 34