What does the “at” (@) symbol do in Python?

Posted on

Solving problem is about exposing yourself to as many situations as possible like What does the “at” (@) symbol do in Python? and practice these strategies over and over. With time, it becomes second nature and a natural way you approach any problems in general. Big or small, always start with a plan, use other strategies mentioned here till you are confident and ready to code the solution.
In this post, my aim is to share an overview the topic about What does the “at” (@) symbol do in Python?, which can be followed any time. Take easy to follow this discuss.

What does the “at” (@) symbol do in Python?

I’m looking at some Python code which used the @ symbol, but I have no idea what it does. I also do not know what to search for as searching Python docs or Google does not return relevant results when the @ symbol is included.

Asked By: AJ00200


Answer #1:

An @ symbol at the beginning of a line is used for class, function and method decorators.

Read more here:

PEP 318: Decorators

Python Decorators

The most common Python decorators you’ll run into are:




If you see an @ in the middle of a line, that’s a different thing, matrix multiplication. Scroll down to see other answers that address that use of @.

Answered By: FogleBird

Answer #2:


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'.
    def __repr__(self):
        return str(self.toppings)
pizza = Pizza()
def cheese():
    return 'cheese'
def sauce():
    return 'sauce'
print pizza
# ['cheese', 'sauce']

This shows that the function/method/class you’re defining after a decorator is just basically passed on as an argument to the function/method immediately after the @ sign.

First sighting

The microframework Flask introduces decorators from the very beginning in the following format:

from flask import Flask
app = Flask(__name__)
def hello():
    return "Hello World!"

This in turn translates to:

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

Realizing this finally allowed me to feel at peace with Flask.

Answered By: Morgan Wilde

Answer #3:

This code snippet:

def decorator(func):
   return func
def some_func():

Is equivalent to this code:

def decorator(func):
    return func
def some_func():
some_func = decorator(some_func)

In the definition of a decorator you can add some modified things that wouldn’t be returned by a function normally.

Answered By: Matheus Araujo

Answer #4:

In Python 3.5 you can overload @ as an operator. It is named as __matmul__, because it is designed to do matrix multiplication, but it can be anything you want. See PEP465 for details.

This is a simple implementation of matrix multiplication.

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)

This code yields:

[[18, 14], [62, 66]]
Answered By: jinhwanlazy

Answer #5:

What does the “at” (@) symbol do in Python?

In short, it is used in decorator syntax and for matrix multiplication.

In the context of decorators, this syntax:

def decorated_function():
    """this function is decorated"""

is equivalent to this:

def decorated_function():
    """this function is decorated"""
decorated_function = decorator(decorated_function)

In the context of matrix multiplication, a @ b invokes a.__matmul__(b) – making this syntax:

a @ b

equivalent to

dot(a, b)


a @= b

equivalent to

a = dot(a, b)

where dot is, for example, the numpy matrix multiplication function and a and b are matrices.

How could you discover this on your own?

I also do not know what to search for as searching Python docs or Google does not return relevant results when the @ symbol is included.

If you want to have a rather complete view of what a particular piece of python syntax does, look directly at the grammar file. For the Python 3 branch:

~$ 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

We can see here that @ is used in three contexts:

  • decorators
  • an operator between factors
  • an augmented assignment operator

Decorator Syntax:

A google search for “decorator python docs” gives as one of the top results, the “Compound Statements” section of the “Python Language Reference.” Scrolling down to the section on function definitions, which we can find by searching for the word, “decorator”, we see that… there’s a lot to read. But the word, “decorator” is a link to the glossary, which tells us:


A function returning another function, usually applied as a function transformation using the @wrapper syntax. Common
examples for decorators are classmethod() and staticmethod().

The decorator syntax is merely syntactic sugar, the following two
function definitions are semantically equivalent:

def f(...):
f = staticmethod(f)
def f(...):

The same concept exists for classes, but is less commonly used there.
See the documentation for function definitions and class definitions
for more about decorators.

So, we see that

def bar():

is semantically the same as:

def bar():
bar = foo(bar)

They are not exactly the same because Python evaluates the foo expression (which could be a dotted lookup and a function call) before bar with the decorator (@) syntax, but evaluates the foo expression after bar in the other case.

(If this difference makes a difference in the meaning of your code, you should reconsider what you’re doing with your life, because that would be pathological.)

Stacked Decorators

If we go back to the function definition syntax documentation, we see:

def func(): pass

is roughly equivalent to

def func(): pass
func = f1(arg)(f2(func))

This is a demonstration that we can call a function that’s a decorator first, as well as stack decorators. Functions, in Python, are first class objects – which means you can pass a function as an argument to another function, and return functions. Decorators do both of these things.

If we stack decorators, the function, as defined, gets passed first to the decorator immediately above it, then the next, and so on.

That about sums up the usage for @ in the context of decorators.

The Operator, @

In the lexical analysis section of the language reference, we have a section on operators, which includes @, which makes it also an operator:

The following tokens are operators:

+       -       *       **      /       //      %      @
<<      >>      &       |       ^       ~
<       >       <=      >=      ==      !=

and in the next page, the Data Model, we have the section Emulating Numeric Types,

object.__add__(self, other)
object.__sub__(self, other)
object.__mul__(self, other)
object.__matmul__(self, other)
object.__truediv__(self, other)
object.__floordiv__(self, other)

These methods are called to implement the binary arithmetic operations (+, -, *, @, /, //, […]

And we see that __matmul__ corresponds to @. If we search the documentation for “matmul” we get a link to What’s new in Python 3.5 with “matmul” under a heading “PEP 465 – A dedicated infix operator for matrix multiplication”.

it can be implemented by defining __matmul__(), __rmatmul__(), and
__imatmul__() for regular, reflected, and in-place matrix multiplication.

(So now we learn that @= is the in-place version). It further explains:

Matrix multiplication is a notably common operation in many fields of
mathematics, science, engineering, and the addition of @ allows
writing cleaner code:

S = (H @ beta - r).T @ inv(H @ V @ H.T) @ (H @ beta - r)

instead of:

S = dot((dot(H, beta) - r).T,
        dot(inv(dot(dot(H, V), H.T)), dot(H, beta) - r))

While this operator can be overloaded to do almost anything, in numpy, for example, we would use this syntax to calculate the inner and outer product of arrays and matrices:

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

Inplace matrix multiplication: @=

While researching the prior usage, we learn that there is also the inplace matrix multiplication. If we attempt to use it, we may find it is not yet implemented for 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'.

When it is implemented, I would expect the result to look like this:

>>> m = matrix([1,2,3])
>>> m @= m.T
>>> m
Answered By: Aaron Hall

Answer #6:

What does the “at” (@) symbol do in Python?

@ symbol is a syntactic sugar python provides to utilize decorator,
to paraphrase the question, It’s exactly about what does decorator do in Python?

Put it simple decorator allow you to modify a given function’s definition without touch its innermost (it’s closure).
It’s the most case when you import wonderful package from third party. You can visualize it, you can use it, but you cannot touch its innermost and its heart.

Here is a quick example,
suppose I define a read_a_book function on 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: '

You see, I forgot to add a name to it.
How to solve such a problem? Of course, I could re-define the function as:

def read_a_book():
    return "I am reading the book: 'Python Cookbook'"

Nevertheless, what if I’m not allowed to manipulate the original function, or if there are thousands of such function to be handled.

Solve the problem by thinking different and define a new_function

def add_a_book(func):
    def wrapper():
        return func() + "Python Cookbook"
    return wrapper

Then employ it.

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, you see, I amended read_a_book without touching it inner closure. Nothing stops me equipped with decorator.

What’s about @

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 is a fancy and handy way to say read_a_book = add_a_book(read_a_book), it’s a syntactic sugar, there’s nothing more fancier about it.

Answered By: Calculus

Answer #7:

If you are referring to some code in a python notebook which is using Numpy library, then @ operator means Matrix Multiplication. For example:

import numpy as np
def forward(xi, W1, b1, W2, b2):
    z1 = W1 @ xi + b1
    a1 = sigma(z1)
    z2 = W2 @ a1 + b2
    return z2, a1
Answered By: f__society

Answer #8:

Decorators were added in Python to make function and method wrapping (a function that receives a function and returns an enhanced one) easier to read and understand. The original use case was to be able to define the methods as class methods or static methods on the head of their definition. Without the decorator syntax, it would require a rather sparse and repetitive definition:

class WithoutDecorators:
def some_static_method():
    print("this is static method")
some_static_method = staticmethod(some_static_method)
def some_class_method(cls):
    print("this is class method")
some_class_method = classmethod(some_class_method)

If the decorator syntax is used for the same purpose, the code is shorter and easier to understand:

class WithDecorators:
    def some_static_method():
        print("this is static method")
    def some_class_method(cls):
        print("this is class method")

General syntax and possible implementations

The decorator is generally a named object ( lambda expressions are not allowed) that accepts a single argument when called (it will be the decorated function) and returns another callable object. “Callable” is used here instead of “function” with premeditation. While decorators are often discussed in the scope of methods and functions, they are not limited to them. In fact, anything that is callable (any object that implements the _call__ method is considered callable), can be used as a decorator and often objects returned by them are not simple functions but more instances of more complex classes implementing their own __call_ method.

The decorator syntax is simply only a syntactic sugar. Consider the following decorator usage:

def decorated_function():

This can always be replaced by an explicit decorator call and function reassignment:

def decorated_function():
decorated_function = some_decorator(decorated_function)

However, the latter is less readable and also very hard to understand if multiple decorators are used on a single function.
Decorators can be used in multiple different ways as shown below:

As a function

There are many ways to write custom decorators, but the simplest way is to write a function that returns a subfunction that wraps the original function call.

The generic patterns is as follows:

def mydecorator(function):
    def wrapped(*args, **kwargs):
        # do some stuff before the original
        # function gets called
        result = function(*args, **kwargs)
        # do some stuff after function call and
        # return the result
        return result
    # return wrapper as a decorated function
    return wrapped

As a class

While decorators almost always can be implemented using functions, there are some situations when using user-defined classes is a better option. This is often true when the decorator needs complex parametrization or it depends on a specific state.

The generic pattern for a nonparametrized decorator as a class is as follows:

class DecoratorAsClass:
    def __init__(self, function):
        self.function = function
    def __call__(self, *args, **kwargs):
        # do some stuff before the original
        # function gets called
        result = self.function(*args, **kwargs)
        # do some stuff after function call and
        # return the result
        return result

Parametrizing decorators

In real code, there is often a need to use decorators that can be parametrized. When the function is used as a decorator, then the solution is simple—a second level of wrapping has to be used. Here is a simple example of the decorator that repeats the execution of a decorated function the specified number of times every time it is called:

def repeat(number=3):
"""Cause decorated function to be repeated a number of times.
Last value of original function call is returned as a result
:param number: number of repetitions, 3 if not specified
def actual_decorator(function):
    def wrapper(*args, **kwargs):
        result = None
        for _ in range(number):
            result = function(*args, **kwargs)
        return result
    return wrapper
return actual_decorator

The decorator defined this way can accept parameters:

>>> @repeat(2)
... def foo():
...     print("foo")
>>> foo()

Note that even if the parametrized decorator has default values for its arguments, the parentheses after its name is required. The correct way to use the preceding decorator with default arguments is as follows:

>>> @repeat()
... def bar():
...     print("bar")
>>> bar()

Finally lets see decorators with Properties.


The properties provide a built-in descriptor type that knows how to link an attribute to a set of methods. A property takes four optional arguments: fget , fset , fdel , and doc . The last one can be provided to define a docstring that is linked to the attribute as if it were a method. Here is an example of a Rectangle class that can be controlled either by direct access to attributes that store two corner points or by using the width , and height properties:

class Rectangle:
    def __init__(self, x1, y1, x2, y2):
        self.x1, self.y1 = x1, y1
        self.x2, self.y2 = x2, y2
    def _width_get(self):
        return self.x2 - self.x1
    def _width_set(self, value):
        self.x2 = self.x1 + value
    def _height_get(self):
        return self.y2 - self.y1
    def _height_set(self, value):
        self.y2 = self.y1 + value
    width = property(
        _width_get, _width_set,
        doc="rectangle width measured from left"
    height = property(
        _height_get, _height_set,
        doc="rectangle height measured from top"
    def __repr__(self):
        return "{}({}, {}, {}, {})".format(
            self.x1, self.y1, self.x2, self.y2

The best syntax for creating properties is using property as a decorator. This will reduce the number of method signatures inside of the class
and make code more readable and maintainable. With decorators the above class becomes:

class Rectangle:
    def __init__(self, x1, y1, x2, y2):
        self.x1, self.y1 = x1, y1
        self.x2, self.y2 = x2, y2
    def width(self):
        """rectangle height measured from top"""
        return self.x2 - self.x1
    def width(self, value):
        self.x2 = self.x1 + value
    def height(self):
        """rectangle height measured from top"""
        return self.y2 - self.y1
    def height(self, value):
        self.y2 = self.y1 + value
Answered By: iun1x

Leave a Reply

Your email address will not be published. Required fields are marked *