numpy.lib.mixins.NDArrayOperatorsMixin#

class numpy.lib.mixins.NDArrayOperatorsMixin[source]#

定义所有运算符特殊方法(使用 __array_ufunc__)的 Mixin。

此类实现了几乎所有 Python 内置运算符的特殊方法,这些运算符定义在 operator 模块中,包括比较运算符(==> 等)和算术运算符(+*- 等),通过推迟到 __array_ufunc__ 方法来实现,子类必须实现此方法。

它对于编写不继承自 numpy.ndarray 但应该像数组一样支持算术运算和 NumPy 通用函数的类很有用,如 重写 Ufunc 的机制 中所述。

作为一个简单的例子,考虑一下 ArrayLike 类的实现,它只包装一个 NumPy 数组,并确保任何算术运算的结果也是一个 ArrayLike 对象。

>>> import numbers
>>> class ArrayLike(np.lib.mixins.NDArrayOperatorsMixin):
...     def __init__(self, value):
...         self.value = np.asarray(value)
...
...     # One might also consider adding the built-in list type to this
...     # list, to support operations like np.add(array_like, list)
...     _HANDLED_TYPES = (np.ndarray, numbers.Number)
...
...     def __array_ufunc__(self, ufunc, method, *inputs, **kwargs):
...         out = kwargs.get('out', ())
...         for x in inputs + out:
...             # Only support operations with instances of
...             # _HANDLED_TYPES. Use ArrayLike instead of type(self)
...             # for isinstance to allow subclasses that don't
...             # override __array_ufunc__ to handle ArrayLike objects.
...             if not isinstance(
...                 x, self._HANDLED_TYPES + (ArrayLike,)
...             ):
...                 return NotImplemented
...
...         # Defer to the implementation of the ufunc
...         # on unwrapped values.
...         inputs = tuple(x.value if isinstance(x, ArrayLike) else x
...                     for x in inputs)
...         if out:
...             kwargs['out'] = tuple(
...                 x.value if isinstance(x, ArrayLike) else x
...                 for x in out)
...         result = getattr(ufunc, method)(*inputs, **kwargs)
...
...         if type(result) is tuple:
...             # multiple return values
...             return tuple(type(self)(x) for x in result)
...         elif method == 'at':
...             # no return value
...             return None
...         else:
...             # one return value
...             return type(self)(result)
...
...     def __repr__(self):
...         return '%s(%r)' % (type(self).__name__, self.value)

ArrayLike 对象与数字或 NumPy 数组之间的交互中,结果始终是另一个 ArrayLike 对象。

>>> x = ArrayLike([1, 2, 3])
>>> x - 1
ArrayLike(array([0, 1, 2]))
>>> 1 - x
ArrayLike(array([ 0, -1, -2]))
>>> np.arange(3) - x
ArrayLike(array([-1, -1, -1]))
>>> x - np.arange(3)
ArrayLike(array([1, 1, 1]))

请注意,与 numpy.ndarray 不同,ArrayLike 不允许与任意未知类型进行运算。这确保了与 ArrayLike 的交互保留了定义良好的转换层次结构。