当前位置: 首页 > 后端技术 > Python

Python3.9中的新功能:任意表达式都可以用作装饰器!

时间:2023-03-26 13:06:41 Python

一个月前(2月20日),新的PEP顺利通过了。这么快的速度,似乎很少见。然而,更高效的是,其实现只用了半个月就集成到了代码仓库中。也就是说,我们有望在3天后(3月23日)在版本3.9.0alpha5中看到它!Python3.9的发布计划:PEP是PEP-614:放宽装饰器的句法限制。当前装饰器的语法为:decorator:'@'dotted_name['('[arglist]')']NEWLINEEPEP-614提议简化为:decorator:'@'namedexpr_testNEWLINEI已翻译PEP全文,Github地址:http://dwz.date/RV9放宽了对装饰器的限制,对之前的使用没有影响,但是至于会带来什么新的好处,我还不知道有什么现实的例子。以下是PEP翻译后的核心内容节选,带大家快速浏览一下:------------节选分割线-----------------总结Python目前要求所有装饰器都包含一个带点的名称,可选地包含一个调用。本PEP提议移除这些限制并允许任何有效的表达式作为装饰器。(译注:点名,指装饰器“@”符号后的“xxx”或“xxx.yyy”格式,没有好的翻译,就不翻译了。)decorator,Guido说对其语法的限制是偏好问题,而不是因为技术要求:我对此有直觉。我不确定它是从哪里来的,但我只是......所以虽然将来将语法更改为@test相当容易,但我想坚持使用更受限制的形式,除非真正使用@test这将增加可读性用例的可能性。尽管在实践中很少遇到问题,但多年来BPO问题和邮件列表帖子不断出现,要求取消限制。最近的一封电子邮件(促使该提议)提供了一段使用PyQt5库的不错的示例代码,如果放宽现有限制,该代码将变得更具可读性、惯用性和可维护性。稍微修改的例子:buttons=[QPushButton(f'Button{i}')foriinrange(10)]#Dostuffwiththelistofbuttons...@buttons[0].clicked.connectdefspam():。..@buttons[1].clicked.connectdefeggs():...#对按钮列表做一些事情...目前,这些装饰必须这样重写但是Python还不支持它,所以你只能使用以下措辞):button_0=buttons[0]@button_0.clicked.connectdefspam():...button_1=buttons[1]@button_1.clicked.connectdefeggs():...另外,当前语法是过于宽容,无法组合更复杂的装饰器表达式。也就是说,当前的限制并没有像预期的那样禁止任意复杂的表达式,它使它们更丑陋且效率更低:#Identityfunctionhack:def_(x):returnx@_(buttons[0].clicked.connect)defspam():...#evalhack:@eval("buttons[1].clicked.connect")defeggs():...原则允许任意表达式现在有一段时间了,决定允许任意有效的表达式(而不是仅仅放宽当前限制,例如允许下标)已被视为装饰器语法演变的下一个合乎逻辑的步骤。正如Guido在另一个邮件列表讨论中所说:我看不出有太多理由强制执行它,因为它不再是一个普通的表达式。专门化语法以允许一些有用的用法只会使当前情况复杂化,并且几乎肯定会在将来的某个时候重复该过程。此外,此句法更改的目的之一是阻止使用eval和上述身份函数反模式的诱惑。简而言之:如果我们想取消一些限制,我们应该取消所有限制。什么算作“表达”在本文档中,“表达”一词的使用定义为《Python语言参考》。可以概括为“任何在if、elif和while块中测试有效的东西”。这与可能更流行的定义略有不同,后者可以概括为“作为有效字符串输入到eval的任何内容”。以前的“表达式”定义更方便,因为它非常符合我们的需要,并允许重用现有语言结构所允许的语法。它与其他定义相比有两个细微差别:1.元组必须加括号这是基于Guido在同一封电子邮件中的见解。紧接着前面的引述:但我不会允许逗号,永远不会赞成这个:@f,gdefpooh():...事实上,它甚至可能导致没有经验的读者得出结论,多个装饰器正在使用设备,因为如果它们堆叠在一起。这里需要括号来明确意图,而不强加进一步的限制和复杂的语法。2.赋值表达式不需要括号到这里,语法的选择就很明确了。PEP572解释了为什么在顶级表达式语句周围需要括号:添加此规则是为了简化用户在赋值语句和赋值表达式之间的选择——没有语法位置两者都有效。由于这里的赋值语句是无效的,所以赋值表达式不需要用括号括起来。(译注:AssignmentExpressions,即AssignmentExpressions或NamedExpressions,是Python3.8引入的新特性,即引入了一个新的“:=”海象运算符。)----------------正文分割线----------------PEP全文翻译已收录在Github的《PEP中文翻译计划》。目前有20多个PEP翻译。欢迎有兴趣的同学查看并参与翻译。附录:PEP614英文:https://www.python.org/dev/peps/pep-0614/PEP614中文:http://dwz.date/RV9PEP中文翻译计划:https://github.com/chinesehuazhou/peps-cn