A month ago (February 20th), a new PEP was officially adopted without any hinders-a speed that seems unusual.

More efficiently, however, its implementation was incorporated into the code repository in just half a month. That said, we can expect to see it in the 3.9.0 Alpha 5 release three days later (March 23) at the soonest!

Release plans for Python 3.9:

This PEP is PEP-614: Relax the syntactic restrictions on decorators.

The current syntax for decorators is:

decorator: The '@' dotted_name [ '(' [arglist] ') ' ] NEWLINE
Copy the code

Pep-614 proposes to simplify this to:

decorator: The '@' namedexpr_test NEWLINE
Copy the code

I have translated the full PEP, Github address: Dz.date /RV9

Relaxing the restrictions on decorators has no effect on previous usage, but I’m not aware of any real-world examples of what new benefits will result.

Here’s an excerpt from PEP’s translation of the core content.

————– Excerpt split line —————-

The profile

Python currently requires that all decorators consist of an dotted name, with an optional call. This PEP proposes to remove these restrictions and allow any valid expression to be used as a decorator.

(The dotted name, which refers to the “XXX” or “XXX. yyy” that followed the “@” sign, represented the embellishers. It was not well translated, so it was not translated.

motivation

When the decorator was first introduced, Guido stated that the syntax restriction was a preference, not a technical requirement:

I have a gut feeling about this. I’m not sure where it came from, but I just have… So while it’s fairly easy to change the syntax to @test in the future, I want to stick with the more restricted form unless I give you a real use case where using @test increases readability.

Although few problems have been encountered in practice, BPO problems and mailing list posts have cropped up over the years asking for restrictions to be removed. A recent email (which led to this proposal) provides a good example of code using the PyQt5 library that would be more readable, native, and maintainable if the existing restrictions were relaxed.

Examples of minor modifications:

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

# Do stuff with the list of buttons...

@buttons[0].clicked.connect
def spam(a):.@buttons[1].clicked.connect
def eggs(a):.# Do stuff with the list of buttons...
Copy the code

Currently, these decorations must be rewritten like this:

button_0 = buttons[0]

@button_0.clicked.connect
def spam(a):. button_1 = buttons[1]

@button_1.clicked.connect
def eggs(a):.Copy the code

In addition, the current syntax is too loose to combine more complex decorator expressions. That is, rather than banning arbitrarily complex expressions as intended, the current restriction makes them uglier and less efficient:

# Identity function hack:

def _(x):
    return x

@_(buttons[0].clicked.connect)
def spam(a):.# eval hack:

@eval("buttons[1].clicked.connect")
def eggs(a):.Copy the code

The principle of

Allow arbitrary expressions

For quite some time, the decision to allow arbitrary valid expressions (rather than just relaxing current restrictions, such as allowing subscripts) has been seen as the next logical step in the development of decorator syntax. As Guido said in another mailing list discussion:

I don’t think it makes sense to force it, because it’s no longer an ordinary expression.

Special Settings of the syntax to allow some useful usage only complicate the current situation and will almost certainly repeat the process at some point in the future. Furthermore, one of the purposes of this syntactic change is to prevent the temptation to use such things as eval and identity-function, the anti-pattern mentioned above.

In short: If we are going to remove some restrictions, we should remove all restrictions.

What is an “expression”?

In this document, the use of the term “expression” is the same as defined in the Python Language Reference. This can be summarized as “anything tested as valid in the if, elif, and while blocks.”

This is a slight departure from the probably more popular definition, which can be summarized as “anything that is input to Eval as a valid string.”

The definition of the former “expression” is more convenient because it fits our needs very well and can reuse the syntax allowed by the existing language structure. It has two subtle differences from other definitions:

1. Tuples must be parentheses

This is based on Guido’s insight in the same email. Immediately following the previous quote:

But I would not allow commas, would never approve of them:

@f, g
def pooh(a):.Copy the code

Indeed, it might even lead the inexperienced reader to conclude that multiple decorators are being used as if they were stacked. Parentheses are required to make the intent clear without imposing further restrictions and complex syntax.

2. Assignment expressions do not need parentheses

Here, the choice of syntax is clear. PEP 572 explains why parentheses are needed around top-level expression statements:

This rule is added to simplify the user’s choice between an assignment statement and an assignment expression — there is no syntactic place for both to work.

Since the assignment statement is not valid here, the assignment expression does not need parentheses.

(Assignment Expressions are a new feature in Python 3.8 that introduces the new “:=” walrus operator.)

—————– Body split line —————

The full translation of PEP has been included in Github’s PEP Chinese Translation Project. There are more than 20 PEP translations available so far.

Appendix:

PEP614 English: www.python.org/dev/peps/pe…

PEP614 英 文 : DZ.date /RV9

PEP Chinese translation program: github.com/chinesehuaz…