Для чого символ "@ =" у Python?


173

Я знаю, що @це для декораторів, але що @=в Python? Це просто застереження для якоїсь майбутньої ідеї?

Це лише одне з моїх численних питань під час читання tokenizer.py.


1
Дивіться cset c553d8f72d65 ( дзеркало GitHub ... легше читати ) у репортажі CPython.
Нік Т

SymbolHound - це пошукова система, яка може шукати розділові знаки. Однак пошук на @ = python наразі не повертає відповідних результатів, оскільки документація Python 3.5 містить "@", але не є прикладом "@ =" в будь-якому місці. Я надіслав SH повідомлення, щоб допомогти покращити це. Python doc також може покращитись.
smci

1
У поєднанні з := оператором моржів Python 3.8 ви отримуєте те, що відоме як @:=оператор тернистих троянд. (Або в Японії він відомий як оператор Елвіс-морж.)
Боб Штейн

Відповіді:


185

З в документації :

Оператор @(at) призначений для використання для матричного множення. Жоден вбудований тип Python не реалізує цей оператор.

@Оператор був введений в Python 3.5. @=- це множення матриць з подальшим призначенням, як ви очікували. Вони відображаються на __matmul__, __rmatmul__або __imatmul__подібно до того , як +і +=зіставити __add__, __radd__або __iadd__.

Оператор та обґрунтування, що стоять за ним, детально обговорюються в PEP 465 .


12
Це пояснює, чому це в останній версії tokenizer.py, але не в 3,4 документа.
Octavia Togami

10
Це висвітлено у документах 3.5 - docs.python.org/3.5/reference/… та docs.python.org/3.5/reference/…
jonrsharpe

Чи це конфлікт з декораторами Python? Це не реалізовано в Python 2.n, правда?
frankliuao

4
Це не суперечить декораторам, оскільки декораторам ніколи не передує вираз, а бінарним операторам завжди повинен передувати вираз.
праворуч

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, а це не так.
Конхілікультор

1
@асоціюється з np.matmul, не np.dot. Два схожі, але не однакові.
Acumenus

@ABB, можливо, ви можете навести приклад, що роз'яснює нюанс і гарантує, що відповідь буде завершена?
benjaminmgross

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.