こんにちはPyQサポートです。今回は、Python 3.8から追加された代入式(セイウチ演算子 :=
)の仕様について紹介します。
質問
代入式(セイウチ演算子)を理解しようとして、
a := "hello"
としたらSyntaxError
が発生しました。print(a := "hello")
はエラーが発生せず、(a := "hello")
もhello
と出力されました。仕様といえばそれまでなのでしょうが、なぜそうなのでしょうか?
実行結果(Python 3.11 インタプリタ)
>>> a:="hello" File "<stdin>", line 1 a:="hello" ^^ SyntaxError: invalid syntax >>> print(a:="hello") hello >>> (a:="hello") 'hello'
回答
a := "hello"
がエラーになって (a := "hello")
がエラーにならない理由は仕様だからです。
この仕様は、下記に記載されています。
- What's New In Python 3.8 — Python 3.8.18 ドキュメント
- PEP 572 – Assignment Expressions | peps.python.org (より詳しい英語での解説)
解説すると、 a := "hello"
だけを書く意味はないので禁止されています。
a := "hello"
だけ書きたければ、 a = "hello"
と書けば良いからです。
また、Pythonの文法上、 a := "hello"
は 式 というものであり、 a = "hello"
は 文 というものです。
式は実行するとオブジェクトを返します。式はそのオブジェクトを使うことに意味があるので、 a := "hello"
だけでは意味がないとみなされています。しかし、(a := "hello")
はエラーにはなりませんが、単独で利用する意味がないのでおすすめしません。
PEP 572 – Assignment Expressions | peps.python.org に以下のような記載があります。
There are a few places where assignment expressions are not allowed, in order to avoid ambiguities or user confusion: Unparenthesized assignment expressions are prohibited at the top level of an expression statement. Example: y := f(x) # INVALID (y := f(x)) # Valid, though not recommended 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.
訳すと以下のようになります。
あいまいさやユーザーの混乱を避けるために、代入式が許可されていない場所があります。 カッコで囲まれていない代入式は、トップのレベルの式では禁止されています。
例
y := f(x) # 無効
(y := f(x)) # 有効だが、おすすめしない
このルールは、ユーザーが代入文と代入式のどちらも簡単に選べるようにするためにあります。
以下は、代入文と代入式をそれぞれ選んだ例です。
代入文を選んだ場合
str_sample = "Hello, Python!" n = len(str_sample) # 代入文 if n > 10: print(n,str_sample)
代入式を選んだ場合
str_sample = "Hello, Python!" if (n :=len(str_sample)) > 10: # 代入式 print(n, str_sample)
What's New In Python 3.8 — Python 3.8.18 ドキュメント には、以下の記述があります。
セイウチ演算子の使用は、複雑さを減らしたり可読性を向上させる綺麗なケースに限るよう努めてください。
代入式(セイウチ演算子)とは
代入式(セイウチ演算子)を説明している記事を紹介します。
以下の記事で、Assignment Expressions(セイウチ演算子)の説明をしています。 blog.pyq.jp
以下のお悩み解決では、セイウチ演算子の利用方法を紹介しています。 blog.pyq.jp