web-dev-qa-db-ja.com

「:=」構文と割り当て式:何と理由?

PEP 572 割り当て式(Walrus Operatorとして知られている)を導入し、Python = 3.8。これは、内包表記およびラムダ関数内でこの形式の割り当てを可能にするため、非常に重要な新機能のようです。

割り当て式の構文、セマンティクス、および文法仕様は正確に何ですか?

PEP 379 on "代入式の追加"」の同様のアイデアが以前に拒否されたとき、なぜこの新しい(そして一見非常に急進的な概念)が導入されるのですか?

29
Chris_Rands

PEP 572 には、特に最初の質問に関する多くの詳細が含まれています。 PEPの最も重要な部分のいくつかを簡潔に要約/引用してみます:

根拠

リスト内包表記などの内包表記、および従来の割り当てが禁止されているラムダ関数内で、この形式の代入を許可します。また、これにより、コードのリファクタリングを必要とせずに、インタラクティブなデバッグが容易になります。

構文とセマンティクス

任意のPython式を使用できるコンテキストでは、という名前の式が表示されます。これは_name := expr_ここで、exprは有効なPython=式、nameは識別子です。

そのような名前付き式の値は、組み込まれた式と同じですが、ターゲットにその値が割り当てられるという追加の副作用があります

通常の割り当てステートメントとの違い

ステートメントではなく式であることに加えて、PEPで言及されているいくつかの違いがあります。式の割り当ては右から左に移動し、コンマを中心に異なる優先度を持ち、サポートしません。

  • 複数のターゲット
_x = y = z = 0  # Equivalent: (z := (y := (x := 0)))
_
  • 単一の名前への割り当て:
_# No equivalent
a[i] = x
self.rest = []
_
  • 反復可能なパッキング/アンパッキング
_# Equivalent needs extra parentheses

loc = x, y  # Use (loc := (x, y))
info = name, phone, *rest  # Use (info := (name, phone, *rest))

# No equivalent

px, py, pz = position
name, phone, email, *other_info = contact
_
  • インラインタイプの注釈:
_# Closest equivalent is "p: Optional[int]" as a separate declaration
p: Optional[int] = None
_
  • 拡張割り当てはサポートされていません:
_total += tax  # Equivalent: (total := total + tax)
_

推奨されるユースケース

a)リスト内包表記の簡素化

例えば:

stuff = [(lambda y: [y,x/y])(f(x)) for x in range(5)]

になることができる:

stuff = [[y := f(x), x/y] for x in range(5)]

b)条件値の取得

たとえば(Python 3)で:

_command = input("> ")
while command != "quit":
    print("You entered:", command)
    command = input("> ")
_

になることができる:

_while (command := input("> ")) != "quit":
    print("You entered:", command)
_
22
Chris_Rands

割り当て式によりコードがより簡潔で読みやすくなるという私のお気に入りの例:

ifステートメント

前:

match = pattern.match(line)
if match:
    return match.group(1)

後:

if match := pattern.match(line):
    return match.group(1)

無限のwhileステートメント

前:

while True:
    data = f.read(1024)
    if not data:
        break
    use(data)

後:

while data := f.read(1024):
    use(data)

PEPの他の良い例 があります。

14