什么是;at";(@)符号在Python中是什么?
我正在看一些使用什么是;at";(@)符号在Python中是什么?,python,syntax,python-decorators,Python,Syntax,Python Decorators,我正在看一些使用@符号的Python代码,但我不知道它是做什么的。我也不知道该搜索什么,因为搜索Python文档时,Google不会返回相关结果,如果包含@符号。它表示您正在使用装饰程序。这是从2008年开始的。行开头的@符号用于类、函数和方法装饰器 请在此处阅读更多信息: 您将遇到的最常见的Python装饰程序有: 如果你在一行中看到一个 @ /代码>,那就不同了,矩阵乘法。 此代码段: def decorator(func): return func @decorator
@
符号的Python代码,但我不知道它是做什么的。我也不知道该搜索什么,因为搜索Python文档时,Google不会返回相关结果,如果包含@
符号。它表示您正在使用装饰程序。这是从2008年开始的。行开头的@
符号用于类、函数和方法装饰器
请在此处阅读更多信息:
您将遇到的最常见的Python装饰程序有:
如果你在一行中看到一个<代码> @ /代码>,那就不同了,矩阵乘法。 此代码段:
def decorator(func):
return func
@decorator
def some_func():
pass
等同于此代码:
def decorator(func):
return func
def some_func():
pass
some_func = decorator(some_func)
在decorator的定义中,您可以添加一些函数通常不会返回的修改内容。示例
这表明函数
/方法
/类
基本上是在@
符号之后,作为参数
传递给函数
/方法
首次见到
微框架烧瓶从一开始就以以下格式引入了装饰器:
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
意识到这一点,我终于对Flask感到心平气和。用另一种方式告诉别人:是的,它是一个装饰师 在Python中,它类似于:
这可以用于各种有用的东西,因为函数是对象,只是必要的指令。在Python 3.5中,您可以作为运算符重载
@
。它被命名为\uuuu matmul\uuuu
,因为它被设计用来进行矩阵乘法,但它可以是您想要的任何东西。有关详细信息,请参阅
这是矩阵乘法的一个简单实现
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]]
从Python 3.5开始,@'被用作矩阵乘法的专用中缀符号(PEP 0465——请参见)在Python中,“at”(@)符号做什么? 简而言之,它用于修饰语法和矩阵乘法
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)
在装饰器的上下文中,以下语法:
@decorator
def decorated_function():
"""this function is decorated"""
a @ b
相当于:
def decorated_function():
"""this function is decorated"""
decorated_function = decorator(decorated_function)
在矩阵乘法的上下文中,a@b
调用a.\uuu matmul\uuuu(b)
-使用以下语法:
@decorator
def decorated_function():
"""this function is decorated"""
a @ b
相当于
dot(a, b)
a = dot(a, b)
及
相当于
dot(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
同样的概念也存在于类中,但在那里不太常用。
有关函数定义和类定义,请参见文档
更多关于装饰师的信息
所以,我们看到了
@foo
def bar():
pass
在语义上与:
def bar():
pass
bar = foo(bar)
它们并不完全相同,因为Python使用decorator(@
)语法在bar之前计算foo表达式(可以是点查找和函数调用),但在另一种情况下在bar之后计算foo表达式
(如果这种差异对代码的意义产生了影响,你应该重新考虑你的生活,因为这是病态的。)
堆叠装饰器
如果我们回到函数定义语法文档,我们会看到:
大致相当于
def func(): pass
func = f1(arg)(f2(func))
这是一个演示,我们可以调用一个函数,它首先是一个decorator,也可以调用堆栈decorator。在Python中,函数是第一类对象——这意味着您可以将函数作为参数传递给另一个函数,并返回函数。装饰师做这两件事
如果我们堆叠decorators,那么函数(如定义的)将首先传递给它上面的decorator,然后传递给下一个,依此类推
这是对装饰器上下文中@
用法的总结
操作员,@
在语言参考的词法分析部分,我们有一个,其中包括@
,这使得它也是一个运算符:
以下令牌是运算符:
+ - * ** / // % @
<< >> & | ^ ~
< > <= >= == !=
[……]
调用这些方法来实现二进制算术运算(+
,-
,*
,@
,/
,[…]
我们看到\uuuu matmul\uuuu
对应于@
。如果我们在文档中搜索“matmul”,我们会在标题“PEP 465-矩阵乘法专用中缀运算符”下找到“matmul”的链接
它可以通过定义\uu matmul\umul()
,\umulta\umul()
和
\uuuu imatmul\uuu()
用于常规、反射和就地矩阵乘法
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)
(现在我们了解到,@=
是就地版本)。它进一步解释:
矩阵乘法是计算机许多领域中一种非常常见的运算
数学、科学、工程和@allows的添加
编写更干净的代码:
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]])
就地矩阵乘法:@=
在研究之前的用法时,
>>> m = matrix([1,2,3])
>>> m @= m.T
>>> m
matrix([[14]])
df = pandas.DataFrame({'foo': [1,2,15,17]})
y = 10
df >> query('foo > @y') # plydata
df.query('foo > @y') # pandas
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'"
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'
@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'
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
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)
class WithDecorators:
@staticmethod
def some_static_method():
print("this is static method")
@classmethod
def some_class_method(cls):
print("this is class method")
@some_decorator
def decorated_function():
pass
def decorated_function():
pass
decorated_function = some_decorator(decorated_function)
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
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
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
>>> @repeat(2)
... def foo():
... print("foo")
...
>>> foo()
foo
foo
>>> @repeat()
... def bar():
... print("bar")
...
>>> bar()
bar
bar
bar
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.__class__.__name__,
self.x1, self.y1, self.x2, self.y2
)
class Rectangle:
def __init__(self, x1, y1, x2, y2):
self.x1, self.y1 = x1, y1
self.x2, self.y2 = x2, y2
@property
def width(self):
"""rectangle height measured from top"""
return self.x2 - self.x1
@width.setter
def width(self, value):
self.x2 = self.x1 + value
@property
def height(self):
"""rectangle height measured from top"""
return self.y2 - self.y1
@height.setter
def height(self, value):
self.y2 = self.y1 + value
def function_decorator(func):
def wrapped_func():
# Do something before the function is executed
func()
# Do something after the function has been executed
return wrapped_func
@function_decorator
def func():
pass
from functools import wraps
def mydecorator(f):
@wraps(f)
def wrapped(*args, **kwargs):
print "Before decorated function"
r = f(*args, **kwargs)
print "After decorated function"
return r
return wrapped
@mydecorator
def myfunc(myarg):
print "my function", myarg
return "return value"
r = myfunc('asdf')
print r
Before decorated function
my function asdf
After decorated function
return value