Что делает символ " at " ( @ ) в Python?

Я смотрю на некоторый код Python, который использовал @ символ, но я понятия не имею, что он делает. Я также не знаю, что искать, поскольку поиск документов Python или Google не возвращает соответствующих результатов, когда @ символ включен.

10 ответов


на @ символ используется для класса, функции и метода декораторы.

подробнее здесь:

PEP 318: декораторы

В Python Декораторы

наиболее распространенными декораторами Python, с которыми вы столкнетесь, являются:

@property

@classmethod

@staticmethod


преамбула

Я признаю, что мне потребовалось больше нескольких минут, чтобы полностью понять эту концепцию, поэтому я поделюсь тем, что узнал, чтобы избавить других от проблем.

имя оформителя - то, что мы определяем с помощью @ синтаксис перед определением функции-вероятно, был главным виновником здесь.

пример

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 вы определяете после оформителя просто в основном передается как 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 после bar в другом случае.

(если эта разница имеет значение для вашего кода, Вы должны пересмотреть то, что вы делаете со своей жизнью, потому что это было бы патологическим.)

группа Декораторы

если мы вернемся к документации синтаксиса определения функции, мы увидим:

@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 - специальный оператор infix для умножения матрицы".

это может быть реализовано путем определения __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: @=

исследуя предыдущее использование, мы узнаем, что существует также умножение матрицы 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, " @ " используется в качестве выделенного символа infix для умножения матрицы (PEP 0465 -- see https://www.python.org/dev/peps/pep-0465/)


что делает символ" at " ( @ ) в Python?

@ symbol является синтаксическим сахар python обеспечивает использовать decorator,
перефразируя вопрос, речь идет именно о том, что делает декоратор в Python?

просто decorator позволяет изменять определение данной функции без касания ее внутренней части (это закрытие).
Это самый случай, когда вы импортируете замечательный пакет от третьей стороны. Ты можешь представить это, ты можешь. используйте его, но вы не можете коснуться его сокровенного и его сердца.

вот пример
предположим, я определяю read_a_book функция на Ipython

In [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, 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 это похоже на:

  1. создание функции (следует под @ call)
  2. вызов другой функции для работы с созданной функцией. Это возвращает новую функцию. Функция, которую вы вызываете, является аргументом @.
  3. замена функции, определенной с возвращаемой новой функцией.

Это можно использовать для всех видов полезного вещи, ставшие возможными, потому что функции-это объекты и просто необходимые инструкции.