最近看 D2L 的代码发现经常会出现下面这样的的情况:在一个类或函数的最前面有个@
。虽然第二章解释了后面的注释#@save
:表示下面的函数是已经定义在包里的,后面不用重新定义便可直接使用。但是并没有解释这里@
的用法。
找了一下资料发现,@
在 Python 中有两种含义:
- 矩阵乘法。
- 类和函数的装饰器。
矩阵乘法
在一些书中,讲到矩阵乘法的时候,会使用matmul
方法进行计算,比如 Pytorch 的torch.matmul
。但其实可以直接使用@
表示矩阵乘法,比如:
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', # 这里的@就是矩阵乘法的意思
globals={'a':a,'b':b}
)
x=t.timeit(50)
2*n**3/x.median/1e12
需要注意这种用法并不是 Pytorch 独有的,如果你查一下 Python 文档的话,会发现文档里就有这种定义。
顺道一提,这个代码我也是从李沐的一篇动态看到的。与此同时,3060 的水平大概是 28,你可以用这个测测你的半精度浮点性能。
类和函数的装饰器
装饰器(decorator)是一种语法糖,也就是用来减少代码量的。它的意思是@
下面的类或函数是@
后面函数的参数。
比如官方文档中有这样一个例子,下面这两个函数的定义是等价的:
def f(arg):
...
f = staticmethod(f)
@staticmethod
def f(arg):
...
你可以看到,staticmethod
的参数就是f
。
那么回到开头那张图中:
首先,LinearRegression
是一个类,前面有定义,只是这里没有列出来。
其次,d2l.add_to_class(LinearRegression)
表示将下面这个函数添加到LinearRegression
这个类中,作为其的一个方法。
这个例子可能你看的还有点迷糊,那么看看这个:
可以看到,model
是LinearRegression
类的一个对象,它在第二张图片的装饰器之后,便可以使用新增的get_w_b()
这个方法。
希望能帮到有需要的人~
参考资料
What does the “at” (@) symbol do in Python? - Stack Overflow:这是一篇帖子中的一个回答。这个回答的质量非常高,虽然不是最高赞,已经说的很全面了,其他的回答都没有必要看。也是我找到答案的起点。
decorator - Glossary - Python:Python 官方文档中关于装饰器的简介,这也是整个文档里唯一单独讲述装饰器的部分。其他都是混着其他内容讲的,如下: