Python中的“ @”(@)符号有什么作用?
我正在看一些使用@
符号的Python代码,但我不知道它的作用。 我也不知道要搜索什么,因为搜索Python文档时会出现,或者当包含@
符号时Google不会返回相关结果。
#1楼
此代码段:
def decorator(func):return func@decorator
def some_func():pass
等效于以下代码:
def decorator(func):return funcdef some_func():passsome_func = decorator(some_func)
在装饰器的定义中,您可以添加一些通常不会由函数返回的修改内容。
#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'.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']
这表明在修饰符之后定义的function
/ method
/ class
基本上只是在@
符号之后作为argument
传递给function
/ method
。
第一次发现
微框架Flask从一开始就以以下格式引入装饰器 :
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和平相处。
#3楼
用不同的方式来说其他人:是的,它是一个装饰器。
在Python中,就像:
- 创建一个函数(在@调用之后)
- 调用另一个函数以对您创建的函数进行操作。 这将返回一个新函数。 您调用的函数是@的参数。
- 用返回的新函数替换定义的函数。
这可以用于各种有用的东西,因为功能是对象,而只是指令而已,因此成为可能。
#4楼
在Python 3.5中,您可以将@
重载为运算符。 它被命名为__matmul__
,因为它旨在进行矩阵乘法,但是它可以是您想要的任何东西。 有关详细信息,请参见PEP465 。
这是矩阵乘法的简单实现。
class Mat(list):def __matmul__(self, B):A = selfreturn 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]]
#5楼
从Python 3.5开始,“ @”用作MATRIX MULTIPLICATION(PEP 0465-参见https://www.python.org/dev/peps/pep-0465/ )的专用中缀符号。
#6楼
Python中的“ @”(@)符号有什么作用?
简而言之,它用于装饰器语法和矩阵乘法。
在装饰器的上下文中,此语法为:
@decorator
def decorated_function():"""this function is decorated"""
等效于此:
def decorated_function():"""this function is decorated"""decorated_function = decorator(decorated_function)
在矩阵乘法的上下文中, a @ b
调用a.__matmul__(b)
-使用以下语法:
a @ b
相当于
dot(a, b)
和
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
我们可以在这里看到@
在三种情况下使用:
- 装饰工
- 因子之间的运算符
- 扩充的赋值运算符
装饰语法:
在Google上搜索“ decorator python docs”时,将“ Python语言参考”的“复合语句”部分作为最高结果之一。 向下滚动至函数定义部分 ,我们可以通过搜索“ decorator”一词找到该部分 ,我们发现……有很多东西可供阅读。 但是“ decorator”这个词是词汇表的链接 ,它告诉我们:
装饰工
返回另一个函数的函数,通常使用
@wrapper
语法作为函数转换应用。 装饰器的常见示例是classmethod()
和staticmethod()
。装饰器语法只是语法糖,以下两个函数定义在语义上是等效的:
def f(...): ... f = staticmethod(f) @staticmethod def f(...): ...
类存在相同的概念,但在该类中较少使用。 有关装饰器的更多信息,请参见函数定义和类定义的文档。
所以,我们看到
@foo
def bar():pass
在语义上与:
def bar():passbar = foo(bar)
它们并不完全相同,因为Python使用装饰器( @
)语法在bar之前评估foo表达式(可能是点分查找和函数调用),但在另一种情况下,则在 bar 之后评估foo表达式。
(如果这种差异使代码的含义有所不同,则应重新考虑自己的生活,因为那会是病态的。)
堆叠式装饰器
如果回到函数定义语法文档,则会看到:
@f1(arg) @f2 def func(): pass
大致相当于
def func(): pass func = f1(arg)(f2(func))
这是一个演示,我们可以调用首先是装饰器的函数以及堆栈装饰器。 在Python中,函数是一流的对象-这意味着您可以将一个函数作为参数传递给另一个函数,然后返回函数。 装饰者可以做这两种事情。
如果我们堆叠装饰器,则已定义的函数会首先传递到紧接其上的装饰器,然后传递给下一个,依此类推。
关于装饰器上下文中@
的用法的总结。
运营商, @
在语言参考的词法分析部分,我们有一个关于运算符的部分 ,其中包括@
,这使其同时也是一个运算符:
以下标记是运算符:
+ - * ** / // % @ << >> & | ^ ~ < > <= >= == !=
在下一页的数据模型中,我们有模拟数字类型一节,
object.__add__(self, other) object.__sub__(self, other) object.__mul__(self, other) object.__matmul__(self, other) object.__truediv__(self, other) object.__floordiv__(self, other)
[...]调用这些方法以实现二进制算术运算(
+
,-
,*
,@
,/
,//
,[...]
并且我们看到__matmul__
对应于@
。 如果我们在文档中搜索“ matmul”,则会在标题“ PEP 465-矩阵乘法的专用中缀运算符”下获得指向“ matmul”的Python 3.5新增功能的链接。
可以通过定义
__matmul__()
,__rmatmul__()
和__imatmul__()
来实现常规,反射和就地矩阵乘法。
(所以现在我们知道@=
是就地版本)。 它进一步说明:
在数学,科学,工程学的许多领域中,矩阵乘法是一种常见的操作,并且@的加法允许编写更简洁的代码:
S = (H @ beta - r).T @ inv(H @ V @ HT) @ (H @ beta - r)
代替:
S = dot((dot(H, beta) - r).T, dot(inv(dot(dot(H, V), HT)), 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]])
就地矩阵乘法: @=
在研究现有用法时,我们了解到还有就地矩阵乘法。 如果尝试使用它,我们可能会发现尚未为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'.
实施后,我希望结果看起来像这样:
>>> m = matrix([1,2,3])
>>> m @= m.T
>>> m
matrix([[14]])
#7楼
@符号还用于访问plydata / pandas数据pandas.DataFrame.query
查询pandas.DataFrame.query
。 例:
df = pandas.DataFrame({'foo': [1,2,15,17]})
y = 10
df >> query('foo > @y') # plydata
df.query('foo > @y') # pandas
#8楼
Python中的“ @”(@)符号有什么作用?
@符号是python提供的使用decorator
的语法糖,
解释这个问题,这恰恰是关于装饰器在Python中的作用?
把它简单的decorator
让你修改一个给定函数的定义,但不接触它的最内层(它的闭包)。
从第三方导入精美的包时,最常见的情况是。 您可以可视化它,可以使用它,但不能触摸它的最内层和内心。
这是一个简单的例子,
假设我在read_a_book
上定义了read_a_book
函数
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'"
但是,如果不允许我操作原始功能,或者要处理成千上万个此类功能,该怎么办。
通过不同的思维来解决问题并定义一个new_function
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'
Tada,您知道,我修改了read_a_book
而不触及它的内部闭包。 没有什么能阻止我配备decorator
。
关于@
什么
@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'
@add_a_book
是花哨和方便的方式来表示read_a_book = add_a_book(read_a_book)
,它是一种语法糖,对此没有什么幻想。
#9楼
如果您在使用Numpy库的python笔记本中引用某些代码,则@ operator
表示矩阵乘法 。 例如:
import numpy as np
def forward(xi, W1, b1, W2, b2):z1 = W1 @ xi + b1a1 = sigma(z1)z2 = W2 @ a1 + b2return z2, a1
#10楼
在Python中添加了装饰器,以使函数和方法包装 (接收函数并返回增强函数的函数)更易于阅读和理解。 最初的用例是能够在定义的顶部将方法定义为类方法或静态方法。 没有装饰器语法,将需要一个相当稀疏且重复的定义:
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:@staticmethoddef some_static_method():print("this is static method")@classmethoddef some_class_method(cls):print("this is class method")
通用语法和可能的实现
装饰器通常是一个命名对象( 不允许使用lambda表达式 ),该对象在被调用时将接受单个参数(它将成为装饰函数)并返回另一个可调用对象。 此处使用“可调用”代替带有预想的“功能”。 尽管装饰器通常在方法和功能的范围内进行讨论,但它们不限于此。 实际上,任何可调用的对象(实现_call__方法的任何对象都被视为可调用的对象)可以用作装饰器,并且它们返回的对象通常不是简单的函数,而是更多复杂类的实例,这些实例实现了自己的__call_方法。
装饰器语法只是一个语法糖 。 考虑以下装饰器用法:
@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 calledresult = function(*args, **kwargs)# do some stuff after function call and# return the resultreturn result# return wrapper as a decorated functionreturn wrapped
上课
尽管装饰器几乎总是可以使用函数来实现,但在某些情况下,使用用户定义的类是更好的选择。 当装饰器需要复杂的参数化或取决于特定状态时,通常会发生这种情况。
非参数化装饰器作为类的通用模式如下:
class DecoratorAsClass:def __init__(self, function):self.function = functiondef __call__(self, *args, **kwargs):# do some stuff before the original# function gets calledresult = self.function(*args, **kwargs)# do some stuff after function call and# return the resultreturn 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 = Nonefor _ in range(number):result = function(*args, **kwargs)return resultreturn wrapper
return actual_decorator
通过这种方式定义的装饰器可以接受参数:
>>> @repeat(2)
... def foo():
... print("foo")
...
>>> foo()
foo
foo
请注意,即使参数化装饰器的参数具有默认值,也必须在其名称后加上括号。 使用带有默认参数的前面装饰器的正确方法如下:
>>> @repeat()
... def bar():
... print("bar")
...
>>> bar()
bar
bar
bar
最后,让我们看看带有Properties的装饰器。
性质
这些属性提供了内置的描述符类型,该描述符类型知道如何将属性链接到一组方法。 一个属性带有四个可选参数:fget,fset,fdel和doc。 可以提供最后一个来定义链接到属性的文档字符串,就好像它是方法一样。 这是一个Rectangle类的示例,可以通过直接访问存储两个角点的属性或使用width和height属性来控制它:
class Rectangle:def __init__(self, x1, y1, x2, y2):self.x1, self.y1 = x1, y1self.x2, self.y2 = x2, y2def _width_get(self):return self.x2 - self.x1def _width_set(self, value):self.x2 = self.x1 + valuedef _height_get(self):return self.y2 - self.y1def _height_set(self, value):self.y2 = self.y1 + valuewidth = 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, y1self.x2, self.y2 = x2, y2@propertydef width(self):"""rectangle height measured from top"""return self.x2 - self.x1@width.setterdef width(self, value):self.x2 = self.x1 + value@propertydef height(self):"""rectangle height measured from top"""return self.y2 - self.y1@height.setterdef height(self, value):self.y2 = self.y1 + value
#11楼
它表明您正在使用装饰器。 这是Bruce Eckel在2008年的例子 。
#12楼
行开头的@
符号用于类,函数和方法修饰符 。
在这里:
PEP 318:装饰器
Python装饰器
您会遇到的最常见的Python装饰器是:
@属性
@classmethod
@staticmethod
如果您在一行的中间看到一个@
,那就是矩阵乘法。 向下滚动以查看其他使用@
答案。
Python中的“ @”(@)符号有什么作用?相关推荐
- python中的@符号的作用
python中的@符号的作用_weixin_34014555的博客-CSDN博客 Python中的" @"(@)符号有什么作用?_p15097962069的博客-CSDN博客
- python 中if __name__ = '__main__' 的作用
python 中if __name__ = '__main__' 的作用 前言 首先我们要知道在python里面万物皆对象,模块也是对象,并且所有的模块都有一个内置属性 __name__. 一个模块的 ...
- python的用途实例-python中pass语句意义与作用(实例分析)
想必大家都是刚刚才开始接触python这门语言的,今天这篇文章就来带大家来了解一下python这门语言之中常常会用到的一个语句pass语句.想必大家都很好奇python中pass作用是什么,接下来我就 ...
- python if else语句例子,python 中if else 语句的作用及示例代码
引入:if-else的作用,满足一个条件做什么,否则做什么. if-else语句语法结构 if 判断条件: 要执行的代码 else: 要执行的代码 判断条件:一般为关系表达式或bool类型的值 执行过 ...
- Python中__init__方法有什么作用
Python中__init__方法有什么作用 当使用类名()的方法去创建对象的时候 python解释器会自动调用__init__方法 因此可以在__init__方法中做一些初始化的设定 在每次创建新对 ...
- python中int函数是什么作用_python中int函数怎么用
python中int函数怎么用,字符串,函数,数字,出现在,赋值 python中int函数怎么用 易采站长站,站长之家为您整理了python中int函数怎么用的相关内容. int() 函数用于将一个字 ...
- python中int函数是什么作用_【后端开发】python中int函数怎么用
int() 函数用于将一个字符串会数字转换为整型.接下来通过本文给大家介绍python 中的int()函数的相关知识,感兴趣的朋友一起看看吧 int(x, [base]) 功能: 函数的作用是将一个数 ...
- python中文件读写位置的作用-python配置文件的读写
1. 配置文件configuration file python中的配置文件有.conf..ini..cfg..txt等多种,其中.ini最常见 .ini文件是Initialization File的 ...
- python中双冒号[::]切片的作用
如:a=[1,2,3.4,5] 我们写:print(a[x:y:z])时,x表示切片起点,y表示切片终点,z表示步长.如果不指定x和y,则默认开始和最后(-1倒序除外),如果不指定z,则默认步长为1. ...
- python中哪个符号用于从包中导入模块__学小易找答案
[简答题]7个积分题 [单选题]5. Is it time for the meeting now? [单选题]result = lambda x: x * x print(result(5)) 以上 ...
最新文章
- BZOJ 2431: [HAOI2009]逆序对数列【DP】
- Android属性动画 监听器、翻转、暂停和恢复
- php考勤分析,php考勤系统
- Win10系列:C#应用控件进阶10
- goland设置goroot_goland安装
- arcpy批量重命名
- 公开下载 |《2021技术人的百宝黑皮书》来了!
- 解决Redis持久化数据丢失
- java 加载3d模型_实现在Java 3D中载入外部3D模型文件方法详解
- JavaScript格式化字符串为指定长度
- 在 Amazon SageMaker 上玩转 Stable Diffusion: 基于 Dreambooth 的模型微调
- ubuntu WPS字体缺失 解决方法
- linux 7 开启远程桌面,CentOS 7 开启VNC远程桌面
- Android点9图机制及在聊天气泡中的应用
- 书论95 蒋骥《续书法论》
- cmake 排除模式
- Swing+IO+Awt实现高级抽奖系统
- rust进水器怎么用_易水香教你如何正确使用家用净水器
- 肖睿:人工智能教育领航者
- iOS - 发送邮件(E-mail)
热门文章
- 【资料整理】cisco [acl]
- 手机壳送你指纹辨识功能,不怕另一半偷看手机了!
- redis内存分析工具rdbtools
- Oracle 索引(转)
- 02~ 一步一步教你使用 SVN之SVN 的介绍
- fedora yum无法正常运行问题的解决
- HTML5 学习(1) -- 介绍
- keepalived高可用使用案例
- ssh远程登录报错Warning: Permanently added ‘111.124.131.312‘ (ECDSA) to the list of known hosts.
- Java语言程序设计(一)填空题