Что делает символ" at " ( @ ) в Python?
Я смотрю на какой-то код на Python, который используется @
символ, но я понятия не имею, что он делает. Я также не знаю, что искать, поскольку поиск документов Python или Google не возвращает соответствующие результаты, когда @
символ включен.
10 ответов:
на
@
символ используется для класса, функции и метода декораторы.подробнее здесь:
наиболее распространенные декораторы Python, с которыми вы столкнетесь:
преамбула
Я признаю, что потребовалось больше, чем несколько минут, чтобы полностью понять эту концепцию для меня, поэтому я поделюсь тем, что я узнал, чтобы избавить других от проблем.
имя оформителя - то, что мы определяем с помощью
@
синтаксис перед определением функции-был, вероятно, главным виновником здесь.пример
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']
это показывает, что
function
/method
/class
вы определяете после a оформителя просто в основном передается какargument
доfunction
/method
сразу после@
знак.первый прицельный
в microframework колбы представляет декораторы С самого начала в следующем формате:
from flask import Flask app = Flask(__name__) @app.route("/") def hello(): return "Hello World!"
это в свою очередь переводится как:
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
осознание этого, наконец, позволило мне чувствовать себя в мире с фляжкой.
этот фрагмент кода:
def decorator(func): return func @decorator def some_func(): pass
эквивалентно этому коду:
def decorator(func): return func def some_func(): pass some_func = decorator(some_func)
в определении декоратора вы можете добавить некоторые измененные вещи, которые обычно не возвращаются функцией.
в Python 3.5 вы можете перегрузить
@
в качестве оператора. Он называется как__matmul__
, потому что он предназначен для умножения матрицы, но это может быть все, что вы хотите. Смотрите PEP465 для сведения.это простая реализация умножения матрицы.
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)
этот код дает:
[[18, 14], [62, 66]]
что делает символ" at " ( @ ) в Python?
короче говоря, он используется в синтаксисе декоратора и для умножения матрицы.
в контексте декораторов, этот синтаксис:
@decorator def decorated_function(): """this function is decorated"""
эквивалентно этому:
def decorated_function(): """this function is decorated""" decorated_function = decorator(decorated_function)
в контексте умножения матриц,
a @ b
вызываетa.__matmul__(b)
- что делает этот синтаксис:a @ b
эквивалентно
dot(a, b)
и
a @= b
эквивалент к
a = dot(a, b)
здесь
dot
это, например, функция умножения матрицы numpy иa
иb
несколько матриц.как вы могли обнаружить это самостоятельно?
я также не знаю, что искать, поскольку поиск документов Python или Google не возвращает соответствующие результаты, когда включен символ@.
если вы хотите иметь довольно полное представление о том, что делает конкретный фрагмент синтаксиса python, посмотрите непосредственно на файл грамматики. Для ветви 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
мы видим здесь, что
@
используется в трех контекстах:
- декораторы
- оператор между факторами
- дополненный оператор присваивания
Синтаксис Декоратора:
поиск google для " декоратор python docs "дает в качестве одного из лучших результатов, раздел" составные операторы "в" Python Language Reference." Прокрутка вниз до раздел об определениях функций, который мы можем найти, ища слово "декоратор", мы это видим... здесь есть что почитать. Но слово, "декоратор" - это ссылка на глоссарий, который говорит нам:
оформителя
функция, возвращающая другую функцию, обычно применяемую в качестве преобразования функции с помощью
@wrapper
синтаксис. Общий примеры для декораторов являютсяclassmethod()
иstaticmethod()
.синтаксис декоратора-это просто синтаксический сахар, следующие два определения функций семантически эквивалентны:
def f(...): ... f = staticmethod(f) @staticmethod def f(...): ...
то же самое понятие существует для классов, но там используется реже. См. документацию для определений функций и определений классов подробнее о декораторах.
Итак, мы видим, что
@foo def bar(): pass
семантически то же самое, что:
def bar(): pass bar = foo(bar)
они не совсем то же самое, потому что Python оценивает выражение foo (которое может быть точечным поиском и вызовом функции) перед баром с декоратором (
@
) синтаксис, но вычисляет выражение foo после бар в другом случае.(если эта разница имеет значение в смысле вашего кода, Вы должны пересмотреть то, что вы делаете со своей жизнью, потому что это было бы патологией.)
группа Декораторы
если мы вернемся к документации синтаксиса определения функции, мы увидим:
@f1(arg) @f2 def func(): pass
примерно эквивалентно
def func(): pass func = f1(arg)(f2(func))
это демонстрация того, что мы можем вызвать функцию, которая сначала является декоратором, а также декораторы стека. Функции в Python являются объектами первого класса - что означает, что вы можете передать функцию в качестве аргумента другой функции и возвращать функции. Декораторы делают оба из них вещи.
если мы складываем декораторы, функция, как определено, передается сначала декоратору непосредственно над ним, затем следующему и так далее.
это о суммирует использование для
@
в контексте декораторов.Оператор
@
в разделе лексического анализа языковой ссылки у нас есть раздел о операторах, которая включает
@
, что делает его также оператор:следующие маркеры являются операторами:
+ - * ** / // % @ << >> & | ^ ~ < > <= >= == !=
и на следующей странице, модель данных, у нас есть раздел, эмулирующий числовые типы,
object.__add__(self, other) object.__sub__(self, other) object.__mul__(self, other) object.__matmul__(self, other) object.__truediv__(self, other) object.__floordiv__(self, other)
[...] Эти методы вызываются для реализации двоичных арифметических операций (
+
,-
,*
,@
,/
,//
, [...]и мы видим, что
__matmul__
соответствует@
. Если мы ищем документацию для "matmul", мы получаем ссылку на что нового в Python 3.5 с "matmul "под заголовком"PEP 465 - специальный оператор инфикса для умножения матриц".это может быть реализовано путем определения
__matmul__()
,__rmatmul__()
, и__imatmul__()
для регулярного, отраженного и матричного умножения на месте.(так что теперь мы узнаем, что
@=
это версия на месте). Далее он объясняет:умножение матрицы заметно общая деятельность в много полей математика, наука, инженерия и добавление @ позволяет написание чистого кода:
S = (H @ beta - r).T @ inv(H @ V @ H.T) @ (H @ beta - r)
вместо:
S = dot((dot(H, beta) - r).T, dot(inv(dot(dot(H, V), H.T)), dot(H, beta) - r))
в то время как этот оператор может быть перегружен, чтобы сделать почти все, в
numpy
например, мы будем использовать этот синтаксис для вычисления внутреннего и внешнего произведения массивов и матриц:>>> 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:
@=
исследуя предыдущее использование, мы узнаем, что существует также умножение матрицы на месте. Если мы попытаемся использовать его, мы можем обнаружить, что он еще не реализован для 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'.
когда он будет реализован, я ожидал бы, что результат будет выглядеть так:
>>> m = matrix([1,2,3]) >>> m @= m.T >>> m matrix([[14]])
начиная с Python 3.5, ' @ ' используется в качестве выделенного символа инфикса для умножения матрицы (PEP 0465 -- см. https://www.python.org/dev/peps/pep-0465/)
что делает символ" at " ( @ ) в Python?
@ symbol-это синтаксический сахар, который python предоставляет для использования
decorator
,
перефразируя вопрос, это именно о том, что делает декоратор в Python?просто
decorator
позволяет изменять определение данной функции, не касаясь ее внутренней части (это закрытие).
Это самый случай, когда вы импортируете замечательный пакет от третьей стороны. Вы можете визуализировать его, вы можете используйте его, но вы не можете коснуться его сокровенного и его сердца.вот пример
предположим, что я определяюread_a_book
функция на IpythonIn [9]: def read_a_book(): ...: return "I am reading the book: " ...: In [10]: read_a_book() Out[10]: 'I am reading the book: '
видите ли, я забыл добавить к нему имя.
Как решить такую проблему? Конечно, я мог бы переопределить функцию как:def read_a_book(): return "I am reading the book: 'Python Cookbook'"
тем не менее, что делать, если мне не разрешено манипулировать исходной функцией, или если есть тысячи таких функций обрабатываемый.
решить проблему, думая по-другому и определить new_function
def add_a_book(func): def wrapper(): return func() + "Python Cookbook" return wrapper
тогда используйте его.
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'
Тада, видишь ли, я поправился
read_a_book
не касаясь его внутреннего закрытия. Ничто не останавливает меня оснащенdecorator
.о
@
@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
это причудливый и удобный способ сказатьread_a_book = add_a_book(read_a_book)
, это синтаксический сахар, в нем нет ничего более причудливого.
@ symbol также используется для доступа к переменным внутри запроса plydata / pandas dataframe,
pandas.DataFrame.query
. Пример:df = pandas.DataFrame({'foo': [1,2,15,17]}) y = 10 df >> query('foo > @y') # plydata df.query('foo > @y') # pandas
Это означает, что вы используете декоратор. Вот это пример Брюса Экеля С 2008 года.
чтобы сказать, что другие имеют по-другому: да, это декоратор.
в Python, это как:
- создание функции (следует под @ call)
- вызов другой функции для работы с созданной функцией. Это возвращает новую функцию. Функции, которые вы называете-это аргумент @.
- замена определенной функции на возвращенную новую функцию.
Это можно использовать для всех видов полезного вещи, ставшие возможными, потому что функции-это объекты и просто необходимые инструкции.