I read PEP 614 (Relaxing Grammar Restrictions On Decorators)
The other day, PEP 614 (Relaxing Grammar Restrictions On Decorators) became Final Commit I saw / python / peps / pull / 1437).
So, this time I will read PEP 614.
Overview
- Previously, only names with
.
, called dotted_name
, were available for decorators.
- Therefore, "expressions" such as array access and dictionary access could not be used for decorators.
buttons = [QPushButton(f'Button {i}') for i in range(10)]
@buttons[0].clicked.connect # => NG
def spam():
...
- Extend the grammar to accept "expressions" in decorators
- Available from Python 3.9.
approach
The grammar so far
decorator: '@' dotted_name [ '(' [arglist] ')' ] NEWLINE
It was
decorator: '@' namedexpr_test NEWLINE
Changed to. that's all.
It's hard to understand that.
namedexpr_test
is a grammatical element that points to a Python expression.
The following are the expressions (from 6. Expressions — Python 3.8.3 Documentation):
- 6.1. Arithmetic conversion
- 6.2. Atom, atomic element (atom)
- 6.2.1. Identifier (or name)
- 6.2.2. Literal
- 6.2.3. Parenthesized form
- 6.2.4. Display of lists, sets and dictionaries
- 6.2.5. List display
- 6.2.6. Collective display
- 6.2.7. Dictionary display
- 6.2.8. Generator type
- 6.2.9. Yield expression
- 6.2.9.1. Generator-Iterator method
- 6.2.9.2. Usage example
- 6.2.9.3. Asynchronous generator function
- 6.2.9.4. Asynchronous generator iterator method
- 6.3. Primary
- 6.3.1. See attributes
- 6.3.2. Subscription
- 6.3.3. Slicing
- 6.3.4. Call
- 6.4. Await expression
- 6.5. Power operator
- 6.6. Unary arithmetic and bitwise operation
- 6.7. Binary arithmetic operation
- 6.8. Shifting operation
- 6.9. Binary bitwise operation
- 6.10. Comparison
- 6.10.1. Value comparison
- 6.10.2. Affiliation inspection calculation
- 6.10.3. Comparison of identity
- 6.11. Boolean operation
- 6.12. Substitution formula
- 6.13. Conditional Expressions
- 6.14. Lambda
- 6.15. List of expressions
There are various things. These are now available for decorators.
Please note that some definitions may not be available (such as await).
Example
Try using a lambda expression as a decorator ...
>>> @lambda f: f
... def foo(): pass
...
Try using the ternary operator if else ...
>>> x = lambda f: f
>>> y = lambda f: f
>>> @x if True else y
... def foo(): pass
...
Of course, you can also use arrays.
>>> deco = [lambda f: f]
>>> @deco[0]
... def foo(): pass
...
Impressions
- I haven't had any problems with dotted_name so far, so I'm not so happy.
- Maybe there's something nice about the decorator array or dictionary ...?
- You need to be careful about the capacity usage because you can write very unpleasant code.
>>> @x := staticmethod #Substitution formula(3.From 9)
... def foo(): pass
...