Для чего нужен символ '@ =' в Python?

173

Я знаю, @что для декораторов, но для чего @=в Python? Это просто резервирование для какой-то будущей идеи?

Это только один из моих многочисленных вопросов во время чтения tokenizer.py.

Октавия Тогами
источник
SymbolHound - это поисковая система, которая может искать символы пунктуации. Однако поиск в @ = python в настоящее время не возвращает релевантных результатов, поскольку документация Python 3.5 содержит @, но нигде не является примером @ =. Я послал SH сообщение, чтобы помочь улучшить это. Документация на Python тоже может улучшиться.
SMCI
1
В сочетании с := оператором моржа Python 3.8 вы получаете то, что известно как @:=оператор тернистой розы. (Или в Японии его называют оператором Элвис-Морж.)
Боб Стейн

Ответы:

185

Из в документации :

Оператор @(at) предназначен для умножения матриц. Нет встроенных типов Python, реализующих этот оператор.

@Оператор был введен в Python 3.5. @=матричное умножение с последующим присваиванием, как и следовало ожидать. Они отображаются на __matmul__, __rmatmul__или __imatmul__подобно тому , как +и +=сопоставить __add__, __radd__или __iadd__.

Оператор и обоснование этого подробно обсуждаются в PEP 465 .

rightfold
источник
12
Это объясняет, почему он находится в последней версии tokenizer.py, но не в документации 3.4.
Октавия Тогами
10
Это описано в документах 3.5 - docs.python.org/3.5/reference/… и docs.python.org/3.5/reference/…
jonrsharpe
Есть ли в этом конфликт с Python-декораторами? Это не реализовано в Python 2.n, верно?
frankliuao
4
Это не противоречит декораторам, потому что декораторам никогда не может предшествовать выражение, а двоичным операторам всегда должно предшествовать выражение.
17
58

@=и @введены ли в Python 3.5 новые операторы, выполняющие умножение матриц . Они призваны прояснить путаницу, существовавшую до сих пор с оператором, *который использовался либо для поэлементного умножения, либо для умножения матриц в зависимости от соглашения, используемого в этой конкретной библиотеке / коде. В результате в будущем оператор *предназначен для использования только для поэлементного умножения.

Как объяснено в PEP0465 , были введены два оператора:

  • Новый бинарный оператор A @ B, используемый аналогичноA * B
  • Версия на месте A @= B, используемая аналогичноA *= B

Матричное Умножение против Поэлементного Умножения

Чтобы быстро выделить разницу, для двух матриц:

A = [[1, 2],    B = [[11, 12],
     [3, 4]]         [13, 14]]
  • Поэлементное умножение даст:

    A * B = [[1 * 11,   2 * 12], 
             [3 * 13,   4 * 14]]
    
  • Матричное умножение даст:

    A @ B  =  [[1 * 11 + 2 * 13,   1 * 12 + 2 * 14],
               [3 * 11 + 4 * 13,   3 * 12 + 4 * 14]]
    

Использование в Numpy

До сих пор Numpy использовал следующее соглашение:

Введение @оператора значительно облегчает чтение кода с умножением матриц. PEP0465 дает нам пример:

# Current implementation of matrix multiplications using dot function
S = np.dot((np.dot(H, beta) - r).T,
            np.dot(inv(np.dot(np.dot(H, V), H.T)), np.dot(H, beta) - r))

# Current implementation of matrix multiplications using dot method
S = (H.dot(beta) - r).T.dot(inv(H.dot(V).dot(H.T))).dot(H.dot(beta) - r)

# Using the @ operator instead
S = (H @ beta - r).T @ inv(H @ V @ H.T) @ (H @ beta - r)

Понятно, что последнюю реализацию гораздо проще читать и интерпретировать как уравнение.

Анджей Пронобис
источник
11
Просто для пояснения: из вашего первого примера мы могли бы подумать, что @было реализовано для list, а это не так.
Conchylicultor
1
@связано np.matmul, а не np.dot. Они похожи, но не одинаковы.
Acumenus
@ABB, возможно, вы могли бы привести пример, поясняющий нюанс и обеспечивающий окончательный ответ?
benjaminmgross