numpy.lib.mixins.NDArrayOperatorsMixin#

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

混合类,使用 __array_ufunc__ 定义所有运算符特殊方法。

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

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

作为一个简单的例子,考虑这个 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 的交互保留了定义明确的转换层次结构。

版本 1.13 中的新内容。