Was bedeutet die @
Symbol in Python tun?
Antworten
Zu viele Anzeigen?Beispiel
class Pizza(object):
def __init__(self):
self.toppings = []
def __call__(self, topping):
# When using '@instance_of_pizza' before a function definition
# the function gets passed onto 'topping'.
self.toppings.append(topping())
def __repr__(self):
return str(self.toppings)
pizza = Pizza()
@pizza
def cheese():
return 'cheese'
@pizza
def sauce():
return 'sauce'
print pizza
# ['cheese', 'sauce']
Dies zeigt, dass die function
/ method
/ class
Sie definieren nach einem Tapezierer wird im Grunde nur als eine argument
à la function
/ method
unmittelbar nach der @
Zeichen.
Erste Sichtung
Der Mikro-Rahmen Flachmann stellt vor Dekorateure von Anfang an in folgendem Format:
from flask import Flask
app = Flask(__name__)
@app.route("/")
def hello():
return "Hello World!"
Dies bedeutet wiederum, dass:
rule = "/"
view_func = hello
# They go as arguments here in 'flask/app.py'
def add_url_rule(self, rule, endpoint=None, view_func=None, **options):
pass
Als ich dies erkannte, konnte ich endlich Frieden mit Flask schließen.
In Python 3.5 können Sie überladen @
als Betreiber. Er wird benannt als __matmul__
weil es für die Matrixmultiplikation konzipiert ist, aber es kann alles sein, was Sie wollen. Siehe PEP465 für Einzelheiten.
Dies ist eine einfache Implementierung der Matrixmultiplikation.
class Mat(list):
def __matmul__(self, B):
A = self
return Mat([[sum(A[i][k]*B[k][j] for k in range(len(B)))
for j in range(len(B[0])) ] for i in range(len(A))])
A = Mat([[1,3],[7,5]])
B = Mat([[6,8],[4,2]])
print(A @ B)
Dieser Code ergibt sich:
[[18, 14], [62, 66]]
Dieses Codeschnipsel:
def decorator(func):
return func
@decorator
def some_func():
pass
Entspricht diesem Code:
def decorator(func):
return func
def some_func():
pass
some_func = decorator(some_func)
In der Definition eines Dekorators können Sie einige geänderte Dinge hinzufügen, die normalerweise nicht von einer Funktion zurückgegeben werden würden.
Welche Funktion hat das Symbol "at" (@) in Python?
Kurz gesagt, es wird in der Dekorator-Syntax und für die Matrixmultiplikation verwendet.
Im Kontext von Dekoratoren ist diese Syntax:
@decorator
def decorated_function():
"""this function is decorated"""
ist gleichbedeutend mit diesem:
def decorated_function():
"""this function is decorated"""
decorated_function = decorator(decorated_function)
Im Zusammenhang mit der Matrixmultiplikation, a @ b
ruft auf. a.__matmul__(b)
- die diese Syntax bilden:
a @ b
gleichbedeutend mit
dot(a, b)
y
a @= b
gleichbedeutend mit
a = dot(a, b)
donde dot
ist zum Beispiel die Numpy-Matrix-Multiplikationsfunktion und a
y b
sind Matrizen.
Wie konnten Sie das selbst herausfinden?
Ich weiß auch nicht, wonach ich suchen soll, da die Suche in den Python-Dokumenten oder bei Google keine relevanten Ergebnisse liefert, wenn das Symbol @ enthalten ist.
Wenn Sie einen ziemlich vollständigen Überblick über die Funktionen einer bestimmten Python-Syntax haben möchten, schauen Sie sich direkt die Grammatikdatei an. Für den Python 3-Zweig:
~$ grep -C 1 "@" cpython/Grammar/Grammar
decorator: '@' dotted_name [ '(' [arglist] ')' ] NEWLINE
decorators: decorator+
--
testlist_star_expr: (test|star_expr) (',' (test|star_expr))* [',']
augassign: ('+=' | '-=' | '*=' | '@=' | '/=' | '%=' | '&=' | '|=' | '^=' |
'<<=' | '>>=' | '**=' | '//=')
--
arith_expr: term (('+'|'-') term)*
term: factor (('*'|'@'|'/'|'%'|'//') factor)*
factor: ('+'|'-'|'~') factor | power
Wir können hier sehen, dass @
wird in drei Kontexten verwendet:
- Dekorateure
- ein Operator zwischen Faktoren
- ein erweiterter Zuweisungsoperator
Decorator-Syntax:
Eine Google-Suche nach "decorator python docs" ergibt als eines der ersten Ergebnisse den Abschnitt "Compound Statements" in der "Python Language Reference". Scrollen Sie hinunter zum Abschnitt Abschnitt über Funktionsdefinitionen die wir finden können, wenn wir nach dem Wort "Dekorateur" suchen, sehen wir, dass... es viel zu lesen gibt. Aber das Wort, "Dekorateur" ist ein Link zum Glossar die uns sagt:
Tapezierer
Eine Funktion, die eine andere Funktion zurückgibt, wird normalerweise als Funktionstransformation mit der
@wrapper
Syntax. Gemeinsame Beispiele für Dekoratoren sindclassmethod()
ystaticmethod()
.Die Dekorsyntax ist lediglich syntaktischer Zucker, die folgenden zwei Funktionsdefinitionen sind semantisch äquivalent:
def f(...): ... f = staticmethod(f) @staticmethod def f(...): ...
Dasselbe Konzept gibt es auch für Klassen, aber es wird dort weniger häufig verwendet. Siehe die Dokumentation für Funktions- und Klassendefinitionen für mehr über Dekoratoren.
Wir sehen also, dass
@foo
def bar():
pass
ist semantisch dasselbe wie:
def bar():
pass
bar = foo(bar)
Sie sind nicht genau dasselbe, weil Python den Ausdruck foo (der ein gepunktetes Lookup und ein Funktionsaufruf sein könnte) vor bar mit dem Dekorator auswertet ( @
) Syntax, sondern wertet den Ausdruck foo aus nach bar in dem anderen Fall.
(Wenn dieser Unterschied einen Unterschied in der Bedeutung Ihres Codes macht, sollten Sie überdenken, was Sie mit Ihrem Leben machen, denn das wäre pathologisch).
Gestapelte Dekorateure
Ein Blick in die Dokumentation der Syntax der Funktionsdefinition zeigt:
@f1(arg) @f2 def func(): pass
ist ungefähr gleichbedeutend mit
def func(): pass func = f1(arg)(f2(func))
Dies ist eine Demonstration dafür, dass wir eine Funktion aufrufen können, die zuerst ein Dekorator ist, ebenso wie Stapeldekoratoren. Funktionen sind in Python Objekte erster Klasse - das heißt, man kann eine Funktion als Argument an eine andere Funktion übergeben und Funktionen zurückgeben. Dekoratoren tun beides.
Wenn wir Dekoratoren stapeln, wird die Funktion, so wie sie definiert ist, zuerst an den unmittelbar darüber liegenden Dekorator übergeben, dann an den nächsten und so weiter.
Das fasst in etwa die Verwendung für @
im Zusammenhang mit Dekorateuren.
Der Operator, @
Im Abschnitt über die lexikalische Analyse der Sprachreferenz gibt es eine Abschnitt über Betreiber die Folgendes umfasst @
und ist somit auch ein Operator:
Die folgenden Token sind Operatoren:
+ - * ** / // % @ << >> & | ^ ~ < > <= >= == !=
und auf der nächsten Seite, dem Datenmodell, haben wir den Abschnitt Numerische Typen emulieren ,
object.__add__(self, other) object.__sub__(self, other) object.__mul__(self, other) object.__matmul__(self, other) object.__truediv__(self, other) object.__floordiv__(self, other)
[...] Diese Methoden werden aufgerufen, um die binären arithmetischen Operationen zu implementieren (
+
,-
,*
,@
,/
,//
, [...]
Und wir sehen, dass __matmul__
entspricht @
. Wenn wir in der Dokumentation nach "matmul" suchen, erhalten wir einen Link zu Was ist neu in Python 3.5 mit "matmul" unter der Überschrift "PEP 465 - A dedicated infix operator for matrix multiplication".
kann sie durch die Definition von
__matmul__()
,__rmatmul__()
y__imatmul__()
für reguläre, reflektierte und In-Place-Matrix-Multiplikation.
(Jetzt erfahren wir also, dass @=
ist die In-Place-Version). Sie erklärt weiter:
Die Matrizenmultiplikation ist in vielen Bereichen der Wissenschaft eine besonders häufige Operation Mathematik, Wissenschaft und Technik, und die Hinzufügung von @ ermöglicht sauberen Code zu schreiben:
S = (H @ beta - r).T @ inv(H @ V @ H.T) @ (H @ beta - r)
anstelle von:
S = dot((dot(H, beta) - r).T, dot(inv(dot(dot(H, V), H.T)), dot(H, beta) - r))
Dieser Operator kann zwar überladen werden und fast alles tun, aber in numpy
Mit dieser Syntax würde man beispielsweise das innere und äußere Produkt von Arrays und Matrizen berechnen:
>>> from numpy import array, matrix
>>> array([[1,2,3]]).T @ array([[1,2,3]])
array([[1, 2, 3],
[2, 4, 6],
[3, 6, 9]])
>>> array([[1,2,3]]) @ array([[1,2,3]]).T
array([[14]])
>>> matrix([1,2,3]).T @ matrix([1,2,3])
matrix([[1, 2, 3],
[2, 4, 6],
[3, 6, 9]])
>>> matrix([1,2,3]) @ matrix([1,2,3]).T
matrix([[14]])
Inplace-Matrix-Multiplikation: @=
Bei der Untersuchung der vorherigen Verwendung erfahren wir, dass es auch die Inplace-Matrix-Multiplikation gibt. Wenn wir versuchen, sie zu verwenden, werden wir feststellen, dass sie für Numpy noch nicht implementiert ist:
>>> m = matrix([1,2,3])
>>> m @= m.T
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: In-place matrix multiplication is not (yet) supported. Use 'a = a @ b' instead of 'a @= b'.
Wenn es umgesetzt wird, würde ich erwarten, dass das Ergebnis wie folgt aussieht:
>>> m = matrix([1,2,3])
>>> m @= m.T
>>> m
matrix([[14]])
- See previous answers
- Weitere Antworten anzeigen