Do czego służy symbol „@ =” w Pythonie?

173

Wiem, że @jest przeznaczony dla dekoratorów, ale po co jest @=w Pythonie? Czy to tylko rezerwacja na jakiś przyszły pomysł?

To tylko jedno z wielu moich pytań podczas czytania tokenizer.py.

Octavia Togami
źródło
1
Zobacz cset c553d8f72d65 ( serwer lustrzany GitHub ... łatwiejszy do odczytania ) w repozytorium CPythona.
Nick T,
SymbolHound to wyszukiwarka, która może wyszukiwać symbole interpunkcyjne. Jednak wyszukiwanie na @ = python obecnie nie zwraca odpowiednich wyników, ponieważ dokumentacja Pythona 3.5 zawiera znak „@”, ale nigdzie nie ma przykładu „@ =”. Wysłałem do SH wiadomość, aby to poprawić. Dokumentacja w Pythonie może również ulec poprawie.
smci,
1
W połączeniu z := operatorem morsa w Pythonie 3.8 otrzymujemy tak zwany @:=operator ciernistej róży. (Lub w Japonii jest znany jako operator Elvisa-morsa.)
Bob Stein

Odpowiedzi:

185

Od tej dokumentacji :

Operator @(at) jest przeznaczony do mnożenia macierzy. Żaden wbudowany typ Pythona nie implementuje tego operatora.

@Operator wprowadza w Pythonie 3.5. @=jest mnożeniem macierzy, po którym następuje przypisanie, jak można się spodziewać. Map one __matmul__, __rmatmul__lub __imatmul__podobny do tego, jak +i +=mapowania __add__, __radd__lub __iadd__.

Operator i jego uzasadnienie omówiono szczegółowo w PEP 465 .

prawy
źródło
12
To wyjaśnia, dlaczego jest w najnowszej wersji tokenizer.py, ale nie w dokumentacji 3.4.
Octavia Togami
10
Jest to omówione w dokumentacji 3.5 - docs.python.org/3.5/reference/… i docs.python.org/3.5/reference/…
jonrsharpe,
Czy ma to konflikt z dekoratorami Pythona? Nie jest to zaimplementowane w Pythonie 2.n, prawda?
frankliuao
4
Nie powoduje to konfliktu z dekoratorami, ponieważ dekoratory nigdy nie mogą być poprzedzone wyrażeniem, a operatory binarne muszą być zawsze poprzedzone wyrażeniem.
prawej
58

@=i @są nowymi operatorami wprowadzonymi w Pythonie 3.5 wykonującymi mnożenie macierzy . Mają one na celu wyjaśnienie istniejącego do tej pory pomyłki z operatorem, *który był używany albo do mnożenia elementów albo mnożenia macierzy, w zależności od konwencji zastosowanej w tej konkretnej bibliotece / kodzie. W rezultacie w przyszłości operator *ma być używany tylko do mnożenia elementów.

Jak wyjaśniono w PEP0465 , wprowadzono dwóch operatorów:

  • Nowy operator binarny A @ B, używany podobnie jakA * B
  • Wersja lokalna A @= B, używana podobnie jakA *= B

Mnożenie macierzy a mnożenie według elementów

Aby szybko podkreślić różnicę, dla dwóch macierzy:

A = [[1, 2],    B = [[11, 12],
     [3, 4]]         [13, 14]]
  • Mnożenie według elementów da:

    A * B = [[1 * 11,   2 * 12], 
             [3 * 13,   4 * 14]]
  • Mnożenie macierzy da:

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

Wykorzystanie w Numpy

Do tej pory Numpy stosował następującą konwencję:

Wprowadzenie @operatora sprawia, że ​​kod zawierający mnożenie macierzy jest znacznie łatwiejszy do odczytania. PEP0465 podaje nam przykład:

# 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)

Oczywiście ostatnia implementacja jest znacznie łatwiejsza do odczytania i zinterpretowania jako równanie.

Andrzej Pronobis
źródło
11
Dla wyjaśnienia: na podstawie Twojego pierwszego przykładu moglibyśmy pomyśleć, że @został on wdrożony list, a tak nie jest.
Conchylicultor
1
@jest związane z np.matmul, a nie np.dot. Są podobne, ale nie takie same.
Acumenus
@ABB, może mógłbyś podać przykład wyjaśniający niuanse i upewniający się, że odpowiedź jest kompletna?
benjaminmgross