Co robi symbol " at " ( @ ) w Pythonie?
Patrzę na jakiś kod Pythona, który używał symbolu @
, ale nie mam pojęcia, co on robi. Nie wiem również, co szukać, ponieważ wyszukiwanie Python docs lub Google nie zwraca odpowiednich wyników, gdy symbol @
jest dołączony.
10 answers
Symbol @
jest używany dla klas, funkcji i metod dekoratorów .
Czytaj więcej tutaj:
Najczęściej spotykanymi dekoratorami Pythona są:
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2011-06-17 23:23:44
Preambuła
Przyznaję, że zajęło mi więcej niż kilka chwil, aby w pełni zrozumieć tę koncepcję, więc podzielę się tym, czego się nauczyłem, aby zaoszczędzić innym kłopotów.
Nazwa dekorator - rzecz, którą definiujemy za pomocą składni @
przed definicją funkcji-była tu prawdopodobnie głównym winowajcą.
Przykład
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']
To pokazuje, że function
/method
/class
definiujesz po dekorator jest w zasadzie przekazywany jako argument
do function
/method
bezpośrednio po znaku @
.
Pierwsza obserwacja
Mikroframework Kolba wprowadza dekoratory od samego początku w następującym formacie:
from flask import Flask
app = Flask(__name__)
@app.route("/")
def hello():
return "Hello World!"
To z kolei tłumaczy się na:
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
Uświadomienie sobie tego w końcu pozwoliło mi poczuć spokój z Flask.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-05-20 13:42:23
Ten fragment kodu:
def decorator(func):
return func
@decorator
def some_func():
pass
Jest odpowiednikiem tego kodu:
def decorator(func):
return func
def some_func():
pass
some_func = decorator(some_func)
W definicji dekoratora można dodać kilka zmodyfikowanych rzeczy, które normalnie nie byłyby zwracane przez funkcję.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-05-20 13:40:12
W Pythonie 3.5 możesz przeciążać @
jako operator. Jest on nazwany __matmul__
, ponieważ jest przeznaczony do mnożenia macierzy, ale może to być wszystko, co chcesz. Zobacz PEP465 Po szczegóły.
Jest to prosta implementacja mnożenia macierzy.
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)
Ten kod daje:
[[18, 14], [62, 66]]
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-05-20 13:44:17
Co robi symbol "at" ( @ ) w Pythonie?
W skrócie, jest używany w składni dekoratora i do mnożenia macierzy.
W kontekście dekoratorów składnia ta:
@decorator
def decorated_function():
"""this function is decorated"""
Jest równoważne temu:
def decorated_function():
"""this function is decorated"""
decorated_function = decorator(decorated_function)
W kontekście mnożenia macierzy, a @ b
wywołuje a.__matmul__(b)
- tworząc tę składnię:
a @ b
Odpowiednik
dot(a, b)
I
a @= b
Odpowiednik
a = dot(a, b)
Gdzie dot
jest, na przykład, numpy funkcja mnożenia macierzy oraz a
i b
są macierzami.
Nie wiem również, co szukać, ponieważ wyszukiwanie Python docs lub Google nie zwraca odpowiednich wyników, gdy symbol @ jest dołączony.
Jeśli chcesz mieć dość kompletny widok tego, co robi dany fragment składni Pythona, spójrz bezpośrednio na plik gramatyki. Dla gałęzi Python 3:
~$ 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
Widzimy tutaj, że @
jest używany w trzech kontekstach:
- dekoratorzy
- operator między czynnikami
- Operator rozszerzonego przydziału
Składnia Dekoratora:
Wyszukiwarka google dla "decorator python docs" daje jako jeden z najlepszych wyników sekcję "Compound Statements" w "Python Language Reference"."Przewijając w dół do sekcji dotyczącej definicji funkcji , którą możemy znaleźć szukając słowa "dekorator", widzimy to... jest dużo do przeczytania. Jednak słowo, "dekorator" jest odnośnikiem do słownika , który mówi nam:
Dekorator
Funkcja zwracająca inną funkcję, zwykle stosowana jako transformacja funkcji przy użyciu składni
@wrapper
. Często przykłady dekoratorów toclassmethod()
istaticmethod()
.Składnia dekoratora jest jedynie cukrem składniowym, następujące dwa definicje funkcji są semantycznie równoważne:
def f(...): ... f = staticmethod(f) @staticmethod def f(...): ...
To samo pojęcie istnieje dla klas, ale jest tam rzadziej używany. Definicje funkcji i klas można znaleźć w dokumentacji więcej o dekoratorach.
Widzimy więc, że
@foo
def bar():
pass
Jest semantycznie takie samo jak:
def bar():
pass
bar = foo(bar)
Nie są dokładnie takie same, ponieważ Python ocenia wyrażenie foo (które może być przeszukiwaniem kropkami i wywołaniem funkcji) przed składnią paska z dekoratorem (@
), ale oblicza wyrażenie foo po pasku w drugim case.
(jeśli ta różnica ma znaczenie w Twoim kodzie, powinieneś przemyśleć to, co robisz ze swoim życiem, ponieważ byłoby to patologiczne.)
Ułożone Dekoratory
Jeśli wrócimy do dokumentacji składni definicji funkcji, zobaczymy:
@f1(arg) @f2 def func(): pass
Jest mniej więcej równoważne
def func(): pass func = f1(arg)(f2(func))
Jest to demonstracja, że możemy najpierw wywołać funkcję, która jest dekoratorem, a także stos dekoratorów. Funkcje, w Pythonie, są obiektami pierwszej klasy - co oznacza, że można przekazać funkcję jako argument do innej funkcji i zwracać funkcje. Dekoratorzy robią obie te rzeczy.
Jeśli stosujemy dekoratory, funkcja, jak zdefiniowano, jest przekazywana najpierw dekoratorowi bezpośrednio nad nim, a następnie następnej, i tak dalej.
Że o podsumowuje użycie dla @
W kontekście dekoratorów.
Operator, @
W sekcji Analiza leksykalna w tym przypadku, jeśli nie jest to możliwe, nie jest to konieczne, ponieważ nie jest to konieczne do osiągnięcia zamierzonego celu.]}
Następujące tokeny są operatorami:
+ - * ** / // % @ << >> & | ^ ~ < > <= >= == !=
I na następnej stronie, model danych, mamy sekcję , emulującą typy numeryczne ,
object.__add__(self, other) object.__sub__(self, other) object.__mul__(self, other) object.__matmul__(self, other) object.__truediv__(self, other) object.__floordiv__(self, other)
[...] Metody te są wywoływane do implementacji binarnych operacji arytmetycznych(
+
,-
,*
,@
,/
,//
, [...]
I widzimy, że __matmul__
odpowiada @
. Jeśli przeszukamy dokumentację pod kątem "matmul", otrzymamy link do Co nowego w Pythonie 3.5 z "matmul" pod nagłówkiem "PEP 465-dedykowany operator infiksu do mnożenia macierzy".
Można go zaimplementować definiując
__matmul__()
,__rmatmul__()
, oraz__imatmul__()
dla mnożenia macierzy regularnej, odbitej i w miejscu.
(więc teraz dowiadujemy się, że @=
jest wersją in-place). To dalej wyjaśnia:
Mnożenie macierzy jest szczególnie powszechną operacją w wielu dziedzinach matematyka, nauki ścisłe, Inżynieria, a dodanie @ pozwala pisanie kodu:
S = (H @ beta - r).T @ inv(H @ V @ H.T) @ (H @ beta - r)
Zamiast:
S = dot((dot(H, beta) - r).T, dot(inv(dot(dot(H, V), H.T)), dot(H, beta) - r))
Chociaż operator ten może być przeciążony, aby zrobić prawie wszystko, na przykład w numpy
, użyjemy tej składni do obliczenia wewnętrznego i zewnętrznego iloczynu tablic i macierzy:
>>> 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]])
Mnożenie macierzy Inplace: @=
Badając wcześniejsze użycie, dowiadujemy się, że istnieje również mnożenie macierzy inplace. Jeśli spróbujemy go użyć, może się okazać, że nie jest jeszcze zaimplementowany dla numpy: {]}
>>> 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'.
Kiedy zostanie zaimplementowany, spodziewam się, że wynik będzie wyglądał tak:
>>> m = matrix([1,2,3])
>>> m @= m.T
>>> m
matrix([[14]])
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-10-05 17:19:02
Począwszy od Pythona 3.5, ' @ ' jest używany jako dedykowany symbol infiksu do mnożenia macierzy (PEP 0465 -- zobacz https://www.python.org/dev/peps/pep-0465/)
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-03-07 23:18:41
Co robi symbol " at " ( @ ) w Pythonie?
@ symbol jest składniowym cukrem, który python dostarcza do wykorzystania decorator
,
parafrazując pytanie, chodzi dokładnie o to, co dekorator robi w Pythonie?
Proste decorator
pozwalają zmodyfikować definicję danej funkcji bez dotykania jej najgłębszej (jest zamknięciem).
Jest to najbardziej przypadek, gdy importujesz wspaniały pakiet od strony trzeciej. Można go wizualizować, można go używać, ale nie można go dotknąć najskrytsze i jego serce.
Oto szybki przykład,
Załóżmy, że definiuję read_a_book
funkcję na Ipythonie
In [9]: def read_a_book():
...: return "I am reading the book: "
...:
In [10]: read_a_book()
Out[10]: 'I am reading the book: '
Widzisz, zapomniałem dodać nazwę do niego.
Jak rozwiązać taki problem? Oczywiście, mógłbym ponownie zdefiniować funkcję jako:
def read_a_book():
return "I am reading the book: 'Python Cookbook'"
Niemniej jednak, co jeśli nie wolno mi manipulować oryginalną funkcją, lub jeśli są tysiące takich funkcji do obsługi.
Rozwiąż problem myśląc inaczej i zdefiniuj new_function
def add_a_book(func):
def wrapper():
return func() + "Python Cookbook"
return wrapper
Więc go wykorzystaj.
In [14]: read_a_book = add_a_book(read_a_book)
In [15]: read_a_book()
Out[15]: 'I am reading the book: Python Cookbook'
Tada, widzisz, zmieniłem read_a_book
nie dotykając tego wewnętrznego zamknięcia. Nic mnie nie powstrzyma.
O co chodzi @
@add_a_book
def read_a_book():
return "I am reading the book: "
In [17]: read_a_book()
Out[17]: 'I am reading the book: Python Cookbook'
@add_a_book
jest fantazyjnym i poręcznym sposobem na powiedzenie read_a_book = add_a_book(read_a_book)
, to cukier składniowy, nie ma w nim nic bardziej fantazyjnego.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-05-26 02:21:07
@ symbol jest również używany do uzyskiwania dostępu do zmiennych wewnątrz zapytania plydata / pandas dataframe, pandas.DataFrame.query
.
Przykład:
df = pandas.DataFrame({'foo': [1,2,15,17]})
y = 10
df >> query('foo > @y') # plydata
df.query('foo > @y') # pandas
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-11-15 21:08:51
Wskazuje, że używasz dekoratora. Oto Przykład Bruce ' a Eckela z 2008 roku.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2011-06-17 23:22:51
Powiedzieć to, co inni mają w inny sposób: tak, to dekorator.
W Pythonie to tak:
- Tworzenie funkcji (następuje pod wywołaniem@)
- wywołanie innej funkcji do działania na utworzonej funkcji. To zwraca nową funkcję. Wywołana funkcja jest argumentem @.
- zastąpienie funkcji zdefiniowanej nową funkcją zwróconą.
To może być używane do wszelkiego rodzaju przydatnych rzeczy, możliwe, ponieważ funkcje są obiektami i tylko niezbędne tylko instrukcje.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-02-07 20:20:26