質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.31%
Python 3.x

Python 3はPythonプログラミング言語の最新バージョンであり、2008年12月3日にリリースされました。

Python

Pythonは、コードの読みやすさが特徴的なプログラミング言語の1つです。 強い型付け、動的型付けに対応しており、後方互換性がないバージョン2系とバージョン3系が使用されています。 商用製品の開発にも無料で使用でき、OSだけでなく仮想環境にも対応。Unicodeによる文字列操作をサポートしているため、日本語処理も標準で可能です。

Q&A

解決済

3回答

1153閲覧

Pythonのウォルラス演算子(セイウチ演算子・代入式)の挙動について教えてください。

exnjinia

総合スコア16

Python 3.x

Python 3はPythonプログラミング言語の最新バージョンであり、2008年12月3日にリリースされました。

Python

Pythonは、コードの読みやすさが特徴的なプログラミング言語の1つです。 強い型付け、動的型付けに対応しており、後方互換性がないバージョン2系とバージョン3系が使用されています。 商用製品の開発にも無料で使用でき、OSだけでなく仮想環境にも対応。Unicodeによる文字列操作をサポートしているため、日本語処理も標準で可能です。

0グッド

1クリップ

投稿2023/07/27 14:49

Pythonのウォルラス(セイウチ)演算子の挙動について教えてください。
(Pythonバージョン:3.9)

発生している事象

下記のコードにおいて、13行目の
if (result := get_batches(check.get(name, 0)))
の箇所をカッコを外し、
if result := get_batches(check.get(name, 0))
とすると、シンタックスエラーが発生します。
なぜカッコでくくらないといけないのでしょうか。

Python

1#リストitemsをキーとして辞書checkの値を確認する。 2#50以上であれば、辞書foundに格納する。 3check = { 4 'A': 100, 5 'B': 80, 6 'C': 40, 7} 8items = ['A', 'B', 'E'] 9 10def get_batches(count): 11 return count // 50 12 13x = {name: result for name in items 14 if (result := get_batches(check.get(name, 0)))} 15print(x)

調べたこと

ウォルラス演算子の左辺にある変数「result」に対し、さらに何かの演算子を使用したいのあれば、カッコが必要であることは理解できます。
たとえば以下のような場合です。

#例1 if (result := get_batches(check.get(name, 0))) Is None #例2 if (result := get_batches(check.get(name, 0))) == 10

この例であれば、「result」への代入を終えた後に、さらに演算子を使用するためにカッコを使うことは理解できます。
しかし、今回はそうしたケースではありません。

「では、ウォルラス演算子をifで使用する場合は、何かと比較をしていなくてもカッコでくくらないといけないというルールが実はあるのか?」
と思い、調べてみましたがそうしたルールは見当たりませんでした。
実際、公式ドキュメントでもウォルラス演算子の項では以下のコードがありました。これはやはりカッコでくくられていません。

if matching := pattern.search(data): do_something(matching)

また、「内包表記の内部でウォルラス演算式を使用する場合は、通常必要ないカッコが必要になるのか?」
とも思いましたが、こちらもそうしたルールは見当たりませんでした。

初歩的すぎる質問で恥ずかしながら自分の知識では、
if (result := get_batches(check.get(name, 0)))
の箇所をカッコを外し、
if result := get_batches(check.get(name, 0))
としたとき、何が原因でシンタックスエラーになってしまっているか理解できずにいます。

どなたか詳しい方ご教示いただけますと幸いです。
よろしくお願いいたします。

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答3

0

この場合、if{...}の中にあるので式の一部であり、if文ではなく三項演算子else項がないものです。この演算子は 優先順位が最も低いので、囲まれた括弧がないと文法的に正しくないです。

不正確な表現を取り消しました。

投稿2023/07/27 15:23

編集2023/07/28 07:40
ikedas

総合スコア4443

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

quickquip

2023/07/28 07:36

(三項演算子の優先度が低いので)リスト内包のif節とパーザに認識されていると思うのですが
ikedas

2023/07/28 07:38

そうですね。「三項演算子のelse項がないもの」と書いてしまってから、書き方が雑だなあと自分でも思っていました。いったん撤回します。
exnjinia

2023/07/30 06:28

回答ありがとうございます! 訂正コメントまでいただき、とても親身になってくださりありがとうございました。
guest

0

まず、以下の式の=の右側の部分は、辞書内包表記というものです。

python

1x = {name: result for name in items 2 if (result := get_batches(check.get(name, 0)))}

辞書内包表記内のifは、6.2.4.リスト、集合、辞書の表示にあるcomp_ifにあたります。

comp_if ::= "if" or_test [comp_iter]

ifの条件に書けるのは、or_testであることが分かります。
このor_testは、6.17.演算子の優先順位における「ブール演算 OR」にあたります。
つまり、この位置には、優先順位表で「ブール演算 OR」までの演算子しか書けません。
それより下の優先順位の式を書きたい場合は、括弧で囲まなければなりません。

※ここから先は、私の推測なので、間違っているかもしれません。

さて、なぜ「ブール演算 OR」までしか書けないようにしているかについてですが、
「ブール演算 OR」の直下にif -- else(条件式)があるのが理由ではないかと推測します。
if -- elseを辞書内包表記内のifの条件に書けるようにしてしまうと、辞書内包表記内のifと区別するのが難しくなります。
セイウチ演算子を括弧で囲む必要があるのは、より優先順位が高いif -- elseのとばっちりを受けているだけのように思います。

投稿2023/07/27 16:11

編集2023/07/27 21:11
actorbug

総合スコア2479

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

exnjinia

2023/07/30 06:26

回答ありがとうございます! 公式ドキュメントの読み方を含め大変勉強になりました。
guest

0

ベストアンサー

と思い、調べてみましたがそうしたルールは見当たりませんでした。

https://docs.python.org/ja/3/reference/expressions.html#assignment-expressions

Assignment expressions must be surrounded by parentheses when used as sub-expressions in slicing, conditional, lambda, keyword-argument, and comprehension-if expressions and in assert and with statements. In all other places where they can be used, parentheses are not required, including in if and while statements.

公式ドキュメントに明記してあります。

(when以下のしかじかの箇所では)代入式は括弧で囲わなければならない。if文やwhile文を含めた、それ以外のところでは括弧は不要である。という内容かと思います。


https://docs.python.org/ja/3/reference/grammar.html の文法定義を見てもそうなっているかと。


追記
括弧が不要なところを挙げると

ifif 代入式:
while 代入式:
スライスの[代入式]
match 代入式,代入式,...:
リストの[代入式,代入式,...]
タプルの(代入式,代入式,...)
setの{代入式,代入式,...}

で、想像だと、記号の : ] } , で終端が判別可能な箇所でだけ括弧を付けなくていいがそれ以外は必要、という基準な気がします。

投稿2023/07/27 15:52

編集2023/07/28 02:12
quickquip

総合スコア11299

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

exnjinia

2023/07/29 17:49

皆さまからとても丁寧な回答をいただき、迷いましたが、自分にとって一番わかりやすかったこちらをベストアンサーとさせていただきました。 本当にありがとうございました。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.31%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問