您好,欢迎访问代理记账网站
移动应用 微信公众号 联系我们

咨询热线 -

电话 15988168888

联系客服
  • 价格透明
  • 信息保密
  • 进度掌控
  • 售后无忧

PEP 614 – Relaxing Grammar Restrictions On Decorators

PEP 614 – Relaxing Grammar Restrictions On Decorators

PEP 614 – 放宽对装饰器的语法限制

PEP:614
Title:Relaxing Grammar Restrictions On Decorators
Author:Brandt Bucher

Contents

  • Abstract,概述
  • Motivation,动机
  • Rationale,理论依据
    • Allowing Any Expression,允许任意的表达式
    • What Counts As An “Expression”,什么算作一个 “表达式”
      • Tuple Displays Must Be Parenthesized,元组显示必须用括号表示
      • Named Expressions Need Not Be Parenthesized,命名的表达式不需要加括号
  • Specification,定义
  • Backwards Compatibility,相后兼容
  • How To Teach This,如何教学
  • Reference Implementation,参考实现
  • Copyright,版权声明

Abstract

概述

Python currently requires that all decorators consist of a dotted name, optionally followed by a single call. This PEP proposes removing these limitations and allowing decorators to be any valid expression.

目前,Python 要求所有的装饰器都由一个带点的名字组成,后面可以有一个单独的调用。本PEP建议取消这些限制,允许装饰器是任何有效的表达式。

Motivation

动机

When decorators were first being introduced, Guido described the motivation to limit their syntax as a preference, not a technical requirement:

当装饰器第一次被引入时,Guido描述了限制其语法的动机是一种偏好,而不是一种技术需要。

I have a gut feeling about this one. I’m not sure where it comes from, but I have it… So while it would be quite easy to change the syntax to @test in the future, I’d like to stick to with the more restricted form unless a real use case is presented where allowing @test would increase readability.

我对这个问题有一种直觉。我不确定它来自哪里,但我有这种感觉… 因此,虽然将来很容易将语法改为@test,但我还是想坚持使用更有限制的形式,除非有真正的用例,允许@test会增加可读性。

While these limitations were rarely encountered in practice, BPO issues and mailing list posts have consistently surfaced over the years requesting that they be removed. The most recent one (which prompted this proposal) contained a good example of code using the PyQt5 library that would become more readable, idiomatic, and maintainable if the existing restrictions were relaxed. Slightly modified:

虽然这些限制在实践中很少遇到,但多年来BPO问题和邮件列表帖子不断出现,要求将其删除。最近的一个帖子(它促使本建议)包含了一个使用PyQt5库的代码的好例子,如果放宽现有的限制,将变得更加可读、习惯和可维护。略有修改:

buttons = [QPushButton(f'Button {i}') for i in range(10)]

# Do stuff with the list of buttons...

@buttons[0].clicked.connect
def spam():
    ...

@buttons[1].clicked.connect
def eggs():
    ...

# Do stuff with the list of buttons...

Currently, these decorations must be rewritten as something like:

目前,这些装饰必须被改写成这样的东西:

button_0 = buttons[0]

@button_0.clicked.connect
def spam():
    ...

button_1 = buttons[1]

@button_1.clicked.connect
def eggs():
    ...

Further, the current grammar is already loose enough that it’s trivial to hack more complicated decorator expressions together. So rather than disallow arbitrarily complex expressions, as intended, the current restrictions only make them uglier and less efficient:

此外,目前的语法已经足够宽松了,以至于把更复杂的装饰器表达式骇在一起是很容易的。因此,目前的限制并没有像预期的那样不允许任意复杂的表达式,而是使它们变得更丑陋,效率更低:

# Identity function hack:

def _(x):
    return x

@_(buttons[0].clicked.connect)
def spam():
    ...

# eval hack:

@eval("buttons[1].clicked.connect")
def eggs():
    ...

原来还可以这么曲线救国…真是眼界大开,语言的缺陷居然可以把开发者逼成这样,译者注。

Rationale

理论依据

Allowing Any Expression

允许任何表达式

The decision to allow any valid expression (and not just relaxing the current restrictions to allow, for example, subscripting) has been considered as the next logical step in the evolution of decorator grammar for quite some time. As Guido noted, during yet another mailing list thread:

允许任何有效表达式的决定(而不仅仅是放宽目前的限制,例如允许下标)被认为是装饰器语法发展的下一个逻辑步骤,已经有相当一段时间了。正如Guido所指出的,在另一个邮件列表线程中:

I don’t think it’s reasonable to constrain it less than it currently is but more than a general expression.

我不认为约束它比目前少,但比一般表达式多是合理的。

Special-casing the grammar to allow some useful cases would only complicate the current situation, and all but guarantee that the process would repeat itself sometime in the future. Further, one purpose of this grammatical change is to discourage the temptation to use hacks like the eval and identity-function anti-patterns shown above.

将语法特殊化以允许一些有用的情况,只会使目前的情况复杂化,而且几乎可以保证这个过程会在未来的某个时候重复。此外,这种语法变化的一个目的是阻止使用像上面所示的eval和identity-function反模式的诱惑。

In short: if we’re removing somewhat arbitrary restrictions, we should remove all of them.

简而言之:如果我们要删除一些任意的限制,我们应该把它们全部删除。

What Counts As An “Expression”

什么算作一个 "表达式

Throughout this document, the word “expression” is used as defined in the Python Language Reference. This can be summarized as “anything that’s valid as a test in if, elif, and while blocks”. This differs subtly from a perhaps more popular definition, which can be summarized as "anything that’s valid as string input to eval".

在本文中,"表达式 "一词是按照Python语言参考中的定义使用的。这可以概括为 “任何在ifelifwhile块中作为测试有效的东西”。这与可能更流行的定义有细微差别,后者可以概括为 “任何可以作为字符串输入到eval的东西”。

This definition of “expression” is convenient in that it fits our needs well, and reuses the allowed grammar of existing language constructs. It has two subtle differences from the other definition:

这个 "表达式 "的定义很方便,因为它很符合我们的需要,并且重用了现有语言结构的允许语法。它与其他定义有两个微妙的区别:

Tuple Displays Must Be Parenthesized

元组显示必须用括号表示

This is based on an observation Guido made in the same email. Continued immediately from above:

这是基于Guido在同一封邮件中的观察。紧接着上面的内容:

Though I wouldn’t allow commas-- there’s no way that

虽然我不允许使用逗号–但不可能有

@f, g
def pooh(): ...

can make sense.

可以说得通。

Indeed, it may even lead inexperienced readers to conclude that several decorators are being applied, as if they were stacked. Requiring parentheses here makes the (admittedly nonsensical) intent clear without imposing further restrictions and grammar complications.

事实上,它甚至可能导致没有经验的读者得出结论,认为几个装饰器正在被应用,就像它们被堆叠起来一样。在这里要求使用圆括号可以清楚地表明(公认是无意义的)意图,而不需要施加进一步的限制和语法上的复杂化。

Named Expressions Need Not Be Parenthesized

命名的表达式不需要加括号

Here, the choice of syntax is unambiguous. PEP 572 explains why it requires parentheses around top-level expression statements:

在这里,语法的选择是毫不含糊的。PEP 572解释了为什么它要求在顶层表达式语句周围加上括号。

This rule is included to simplify the choice for the user between an assignment statement and an assignment expression – there is no syntactic position where both are valid.

包括这条规则是为了简化用户在赋值语句和赋值表达式之间的选择–没有一个语法位置是两者都有效的。

Since an assignment statement is not valid here, assignment expressions should not be unnecessarily burdened with parentheses.

由于赋值语句在这里是无效的,所以赋值表达式不应该有不必要的括号负担。

Specification

定义

The grammar for decorators is currently:

目前,装饰者的语法是:

decorator: '@' dotted_name [ '(' [arglist] ')' ] NEWLINE

This PEP proposes that it be simplified to:

本PEP建议将其简化为:

decorator: '@' namedexpr_test NEWLINE

Backwards Compatibility

向后兼容

This new grammar is fully backward-compatible with the existing grammar.

这个新的语法与现有的语法完全向后兼容。

How To Teach This

如何教学

Decorators can continue to be taught as they always have; the average Python programmer is likely unaware that the current restriction even exists.

装饰器可以继续像以前一样被教授;一般的Python程序员可能不知道目前的限制存在。

Reference Implementation

参考实现

The author has written a CPython implementation.

作者写了一个CPython的实现。

Copyright

版权声明

This document is placed in the public domain or under the CC0-1.0-Universal license, whichever is more permissive.

本文件被置于公共领域或CC0-1.0-Universal许可之下,以更多许可为准。

Source: https://github.com/python/peps/blob/master/pep-0614.rst

版权声明:本文由 icexmoon 翻译,遵循CC 4.0 BY-SA版权协议。


分享:

低价透明

统一报价,无隐形消费

金牌服务

一对一专属顾问7*24小时金牌服务

信息保密

个人信息安全有保障

售后无忧

服务出问题客服经理全程跟进