0
2

More than 3 years have passed since last update.

PEP 614 (Relaxing Grammar Restrictions On Decorators) を読んだよメモ

Posted at

先日、PEP 614 (Relaxing Grammar Restrictions On Decorators)Final になったというコミットを見かけました。
そこで、今回は PEP 614 を読んでみようと思います。

概要

  • これまでデコレータに利用できるのは dotted_name と呼ばれる、. つきの名前のみだった
  • そのため、配列アクセスや辞書アクセスといった「式」の類はデコレータには使えなかった
  buttons = [QPushButton(f'Button {i}') for i in range(10)]

  @buttons[0].clicked.connect  # => NG
  def spam():
      ...
  • 文法を拡張して、デコレータに「式」を受け付けるようにした
  • Python 3.9 から利用できます。

アプローチ

いままでの文法が

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

だったのを

decorator: '@' namedexpr_test NEWLINE

に変更しました。以上。

って、それだと分かりづらいですね。
namedexpr_test は Python の式(expression)を指す文法要素です。
式に該当するのは以下のものです (6. 式 (expression) — Python 3.8.3 ドキュメント より)。

  • 6.1. 算術変換 (arithmetic conversion)
  • 6.2. アトム、原子的要素 (atom)
  • 6.2.1. 識別子 (identifier、または名前 (name))
  • 6.2.2. リテラル
  • 6.2.3. 丸括弧形式 (parenthesized form)
  • 6.2.4. リスト、集合、辞書の表示
  • 6.2.5. リスト表示
  • 6.2.6. 集合表示
  • 6.2.7. 辞書表示
  • 6.2.8. ジェネレータ式
  • 6.2.9. Yield 式
  • 6.2.9.1. ジェネレータ-イテレータメソッド
  • 6.2.9.2. 使用例
  • 6.2.9.3. 非同期ジェネレータ関数 (asynchronous generator function)
  • 6.2.9.4. 非同期ジェネレータイテレータメソッド
  • 6.3. プライマリ
  • 6.3.1. 属性参照
  • 6.3.2. 添字表記 (subscription)
  • 6.3.3. スライス表記 (slicing)
  • 6.3.4. 呼び出し (call)
  • 6.4. Await 式
  • 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. 比較
  • 6.10.1. 値の比較
  • 6.10.2. 所属検査演算
  • 6.10.3. 同一性の比較
  • 6.11. ブール演算 (boolean operation)
  • 6.12. 代入式
  • 6.13. 条件式 (Conditional Expressions)
  • 6.14. ラムダ (lambda)
  • 6.15. 式のリスト

いろいろありますね。これらがデコレータに利用できるようになったというわけです。
定義場所によっては使えないものもある(await とか)ことには注意してください。

デコレータに lambda 式を使ってみたり...

>>> @lambda f: f
... def foo(): pass
...

三項演算子的な if else を使ってみたり...

>>> x = lambda f: f
>>> y = lambda f: f
>>> @x if True else y
... def foo(): pass
...

もちろん、配列も使えます。

>>> deco = [lambda f: f]
>>> @deco[0]
... def foo(): pass
...

感想

  • いままで dotted_name で困っていなかったので、嬉しさがあまりピンとこない
  • デコレータの配列や辞書で嬉しいことがあるのかも…?
  • すごく気持ち悪いコードが書けてしまうので、容量用法には注意が必要です。
  >>> @x := staticmethod  # 代入式 (3.9 より)
  ... def foo(): pass
  ...
0
2
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
2