Home Swift UNIX C Assembly Go Web MCU Research Non-Tech

What Does the "@" Symbol Do in Python? Explaining Its Two Key Uses in D2L Code

2025-01-22 | Research | #Words: 720 | 中文原版

Recently, while going through D2L (Dive into Deep Learning) code, I frequently noticed the “@” symbol appearing at the very top of classes or functions. Although Chapter 2 explains the comment #@save (indicating the following function is pre-defined in the package and can be used directly without redefinition), it does not explain the usage of the “@” symbol itself.

D2L code snippet showing @ symbol before a function

After researching, I found that “@” has two main meanings in Python:

  1. Matrix multiplication
  2. Decorators for classes and functions

1. Matrix Multiplication

In some textbooks, matrix multiplication is calculated using the matmul method (e.g., PyTorch’s torch.matmul). However, you can directly use “@” to represent matrix multiplication, as shown in this example:

import torch
from torch.utils import benchmark
typ = torch.float16
n = 1024*16
a = torch.randn(n,n).type(typ).cuda()
b = torch.randn(n,n).type(typ).cuda()
t = benchmark.Timer (
    stmt='a @ b', # The "@" here means matrix multiplication
    globals={'a':a,'b':b}
)
x=t.timeit(50)
2*n**3/x.median/1e12

Note: This usage is not exclusive to PyTorch—you’ll find it defined in the official Python documentation as well.

As an aside, I came across this code in one of Li Mu’s posts. For reference, the RTX 3060 scores around 28 on this benchmark—you can use it to test your GPU’s FP16 (half-precision floating-point) performance.

FP16 performance benchmark result for RTX 3060

2. Decorators for Classes and Functions

A decorator is a form of syntactic sugar (designed to reduce code redundancy). It means the class/function below the “@” symbol is passed as an argument to the function following the “@”.

For example, the official Python documentation provides this example—these two function definitions are equivalent:

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

As you can see, f is the argument to staticmethod.

Now let’s return to the code snippet from the start:

D2L code snippet with @d2l.add_to_class decorator

First, LinearRegression is a pre-defined class (not shown in the snippet). Second, d2l.add_to_class(LinearRegression) means the following function is added to the LinearRegression class as one of its methods.

If this example is still confusing, take a look at these screenshots:

Code showing LinearRegression class instantiation
Code showing get_w_b() method available after decorator usage

You can see that model (an instance of the LinearRegression class) gains access to the newly added get_w_b() method after the decorator is applied.

I hope these will help someone in need~

References

Python official documentation snippet about decorators