Как работает numpy дополнение? - PullRequest
0 голосов
/ 14 мая 2018

У меня неожиданное поведение

import numpy as np
class Test:
    def __radd__(self, other):
        print(f'value: {other}')

[1,2,3] + Test()
# prints: value: [1,2,3]
np.array([1,2,3]) + Test()
# prints
# value: 1
# value: 2
# value: 3

Я ожидаю, что второе дополнение будет вести себя так же, как и первое, но это не так. Единственное логическое объяснение, которое я вижу, состоит в том, что оператор numpy + каким-то образом перебирает сначала аргументы и пытается добавить каждый из них к Test(), а второе добавление (int + Test) возвращается к Test.__radd__

So

  • Есть ли еще какое-то объяснение, по которому я скучаю?
  • если нет, то как a + b работает в numpy
  • это эквивалентно np.add(a, b)?

Ответы [ 3 ]

0 голосов
/ 14 мая 2018

Это из-за 'NumPy ' широковещания '.

Ваше объяснение в значительной степени верно, поскольку вы можете видеть в документах для np.add.

Примечания

Эквивалент x1 + x2 с точки зрения вещания массива.

Я считаю, что это имеет немного больше смысла, если выпоиграйте с NumPy и посмотрите, чем np.array отличается от встроенного списка.

Python 3.5.2 (default, Jul  6 2016, 16:37:16)
Type 'copyright', 'credits' or 'license' for more information
IPython 6.2.1 -- An enhanced Interactive Python. Type '?' for help.

In [1]: import numpy as np

In [2]: [1, 2, 3] + [1, 2, 3]
Out[2]: [1, 2, 3, 1, 2, 3]

In [3]: np.array([1, 2, 3]) + np.array([1, 2, 3])
Out[3]: array([2, 4, 6])

Глядя на исходный код здесь для NDArrayOperatorsMixin, который implements the special methods for almost all of Python's builtin operators defined in the `operator` module.Похоже, что __add__, __radd__, __iadd__ все настроены на функцию .add umath. Но Я не уверен, что фактический ndarray использует микширование, я думаю, вам придется копаться в коде C, чтобы выяснить, как это обрабатывается.

0 голосов
/ 14 мая 2018

Если я немного расширю ваш класс, мы можем получить больше представления о том, когда используется __add__ и когда __radd__:

class Test:
    def __radd__(self, other):
        print(f'r value: {other}, {type(other)}')
        return f'{other}'
    def __add__(self, other):
        print(f'a value: {other}, {type(other)}')
        return other+3

Со списком

In [285]: [1,2,3]+Test()
r value: [1, 2, 3], <class 'list'>    # use Test.__radd__
Out[285]: '[1, 2, 3]'
In [286]: Test()+[1,2,3]             # tries to use Test.__add__
a value: [1, 2, 3], <class 'list'>
....
<ipython-input-280-cd3f564be47a> in __add__(self, other)
      5     def __add__(self, other):
      6         print(f'a value: {other}, {type(other)}')
----> 7         return other+3
      8 
TypeError: can only concatenate list (not "int") to list

С массивом:

In [287]: np.arange(3)+Test()     # use Test.__radd__ with each array element
r value: 0, <class 'int'>
r value: 1, <class 'int'>
r value: 2, <class 'int'>
Out[287]: array(['0', '1', '2'], dtype=object)
In [288]: Test()+np.arange(3)
a value: [0 1 2], <class 'numpy.ndarray'>
Out[288]: array([3, 4, 5])    # use Test.__add__ on whole array

Сам по себе, двойное использование Test.__add__:

In [289]: Test()+Test()
a value: <__main__.Test object at 0x7fc33a5a7a20>, <class '__main__.Test'>
a value: 3, <class 'int'>
Out[289]: 6

Как я уже говорил, это может быть сложно разобрать __add__ v __radd__ делегирование и отделение этого от действия ndarray.


add с Test() секундой дает тот же результат, что и [287]:

In [295]: np.add(np.arange(3),Test())
r value: 0, <class 'int'>
r value: 1, <class 'int'>
r value: 2, <class 'int'>
Out[295]: array(['0', '1', '2'], dtype=object)

np.add с Test() сначала отличается от [288] выше:

In [296]: np.add(Test(),np.arange(3))
a value: 0, <class 'int'>
a value: 1, <class 'int'>
a value: 2, <class 'int'>
Out[296]: array([3, 4, 5], dtype=object)
0 голосов
/ 14 мая 2018

Ваша интуиция верна. Numpy добавляет каждый элемент. Вы можете увидеть это поведение и с примитивами:

np.array([1,2,3]) + 1  # [2,3,4]
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...