What does the “at” (@) symbol do in Python?
我在看一些使用
序言
我承认,我花了很长时间才完全理解这个概念,所以我将分享我所学到的,以拯救别人的麻烦。
名称修饰器——我们在函数定义之前使用
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 | 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'] |
这表明,你定义的
微框架烧瓶从一开始就以以下格式介绍装饰师:
1 2 3 4 5 6 | from flask import Flask app = Flask(__name__) @app.route("/") def hello(): return"Hello World!" |
这反过来就意味着:
1 2 3 4 5 | 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 |
意识到这一点,我终于感觉到和烧瓶的平静。
行首的
在这里阅读更多:
PEP 318:装饰师
Python装饰师
您遇到的最常见的python装饰器是:
@房产
@类方法
静力法
如果你在一行的中间看到一个
此代码段:
1 2 3 4 5 6 | def decorator(func): return func @decorator def some_func(): pass |
等同于此代码:
1 2 3 4 5 6 7 | def decorator(func): return func def some_func(): pass some_func = decorator(some_func) |
在decorator的定义中,可以添加一些通常函数不会返回的修改内容。
在python3.5中,可以将
这是矩阵乘法的一个简单实现。
1 2 3 4 5 6 7 8 9 10 | 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) |
此代码生成:
1 | [[18, 14], [62, 66]] |
"at"(@)符号在python中有什么作用?
简而言之,它用于修饰语法和矩阵乘法。
在decorator上下文中,此语法:
1 2 3 | @decorator def decorated_function(): """this function is decorated""" |
相当于:
1 2 3 4 | def decorated_function(): """this function is decorated""" decorated_function = decorator(decorated_function) |
在矩阵乘法的上下文中,
1 | a @ b |
相当于
1 | dot(a, b) |
和
1 | a @= b |
相当于
1 | a = dot(a, b) |
其中
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.
如果您想对特定的Python语法有一个比较完整的了解,可以直接查看语法文件。对于python 3分支:
1 2 3 4 5 6 7 8 9 10 11 12 | ~$ 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 |
我们可以看到,
- 装饰者
- 因子之间的运算符
- 增广的赋值运算符
修饰语法:
谷歌搜索"decorator python docs"的结果之一是"python language reference"的"compound statements"部分。向下滚动到函数定义部分,我们可以通过搜索"decorator"一词找到该部分,我们看到…有很多书要读。但是"decorator"这个词是词汇表的链接,它告诉我们:
decorator
A function returning another function, usually applied as a function transformation using the
@wrapper syntax. Common
examples for decorators areclassmethod() andstaticmethod() .The decorator syntax is merely syntactic sugar, the following two
function definitions are semantically equivalent:
1
2
3
4
5
6
7 def f(...):
...
f = staticmethod(f)
@staticmethod
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.
所以,我们看到
1 2 3 | @foo def bar(): pass |
在语义上与以下内容相同:
1 2 3 4 | def bar(): pass bar = foo(bar) |
它们并不完全相同,因为python使用decorator(
(如果此差异对代码的含义造成影响,则应重新考虑您的生活在做什么,因为这将是病态的。)
堆积装饰工如果我们回到函数定义语法文档,我们会看到:
1
2
3 @f1(arg)
@f2
def func(): passis roughly equivalent to
1
2 def func(): pass
func = f1(arg)(f2(func))
这是一个演示,我们可以先调用一个修饰符函数,然后调用堆栈修饰符。在Python中,函数是第一类对象——这意味着您可以将函数作为参数传递给另一个函数,并返回函数。装饰师做这两件事。
如果我们堆栈decorator,那么定义好的函数首先被传递给紧挨着它上面的decorator,然后传递给下一个,依此类推。
这大概总结了
在语言参考的词汇分析部分,我们有一个关于运算符的部分,其中包括
The following tokens are operators:
1
2
3 + - * ** / // % @
<< >> & | ^ ~
< > <= >= == !=
在下一页的数据模型中,我们有一节,模拟数字类型,
1
2
3
4
5
6 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 (+ ,- ,* ,@ ,/ ,// , [...]
我们看到
it can be implemented by defining
__matmul__() ,__rmatmul__() , and
__imatmul__() for regular, reflected, and in-place matrix multiplication.
(现在我们了解到,
Matrix multiplication is a notably common operation in many fields of
mathematics, science, engineering, and the addition of @ allows
writing cleaner code:
1 S = (H @ beta - r).T @ inv(H @ V @ H.T) @ (H @ beta - r)instead of:
1
2 S = dot((dot(H, beta) - r).T,
dot(inv(dot(dot(H, V), H.T)), dot(H, beta) - r))
虽然这个操作符可以被重载来做几乎任何事情,例如在
1 2 3 4 5 6 7 8 9 10 11 12 13 | >>> 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]]) |
在位矩阵乘法:
在研究先前的用法的同时,我们了解到还有就地矩阵乘法。如果我们尝试使用它,我们可能会发现它还没有为numpy实现:
1 2 3 4 5 | >>> 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'. |
当它被实现时,我希望结果是这样的:
1 2 3 4 | >>> m = matrix([1,2,3]) >>> m @= m.T >>> m matrix([[14]]) |
What does the"at" (@) symbol do in Python?
@符号是python提供使用
简单地说,
下面是一个简单的例子,假设我在ipython上定义了一个
1 2 3 4 5 | In [9]: def read_a_book(): ...: return"I am reading the book:" ...: In [10]: read_a_book() Out[10]: 'I am reading the book: ' |
你看,我忘了给它加个名字。如何解决这个问题?当然,我可以将函数重新定义为:
1 2 | def read_a_book(): return"I am reading the book: 'Python Cookbook'" |
然而,如果不允许我操作原始函数,或者如果有数千个这样的函数需要处理,该怎么办呢?
用不同的思维来解决问题,并定义一个新的函数
1 2 3 4 | def add_a_book(func): def wrapper(): return func() +"Python Cookbook" return wrapper |
然后使用它。
1 2 3 | 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' |
塔达,你看,我修改了
关于
1 2 3 4 5 | @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' |
如果您指的是使用numpy库的python笔记本中的一些代码,那么
1 2 3 4 5 6 | 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 |
从python 3.5开始,"@"用作矩阵乘法的专用中缀符号(pep 0465--请参阅https://www.python.org/dev/peps/pep-0465/)
@符号还用于访问plydata/pandas数据帧查询(
1 2 3 4 | df = pandas.DataFrame({'foo': [1,2,15,17]}) y = 10 df >> query('foo > @y') # plydata df.query('foo > @y') # pandas |
用另一种方式说别人有什么:是的,这是一个装饰师。
在python中,它就像:
这可以用于各种有用的事物,之所以成为可能,是因为函数是对象,只是必需的指令。
它表示您正在使用一个装饰器。下面是BruceEckel 2008年的例子。