958 Stimmen

Welche Funktion hat das Symbol "at" (@) in Python?

Was bedeutet die @ Symbol in Python tun?

578voto

FogleBird Punkte 69852

Eine @ Symbol an der Anfang einer Zeile wird für Klasse und Funktion verwendet Dekorateure :

Die gebräuchlichsten Python-Dekoratoren sind:

Eine @ en el Mitte einer Zeile ist wahrscheinlich eine Matrixmultiplikation:

454voto

Morgan Wilde Punkte 16073

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.

321voto

jinhwanlazy Punkte 2711

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]]

274voto

Matheus Araujo Punkte 5123

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.

187voto

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 sind classmethod() y staticmethod() .

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

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X