44

タプルのアンパックについては知っていますが、1 行に複数の等号がある場合、この割り当ては何と呼ばれますか? あらa = b = True

特に RHS が変更可能である場合は、常に少しつまずきますが、ドキュメントで検索する適切なキーワードを見つけるのに本当に苦労しています。

4

4 に答える 4

71

それは割り当ての連鎖であり、それを説明するために使用される用語は...

- ドラムロールをお願いできますか?

連鎖代入


私はそれをグーグルで実行したところ、おそらくほとんどの人が非常に簡単に使用できると感じているため、このトピックについて読むことはあまりないことがわかりました(そして、真のオタクだけがこのトピックについてもっと知りたいと思っています) .


=前の式では、評価の順序は右端から始まり、左に向かって進むと見なすことができます。これは、次のように書くことと同じです。

b = True
a = b

上記の順序は、ほとんどの言語が割り当てチェーンを説明するものですが、python は別の方法で行います。Python では、式は以下の同等のものとして評価されますが、前に説明した以外の結果にはなりません。

temporary_expr_result = True

a = temporary_expr_result
b = temporary_expr_result

stackoverflow でさらに読むことができます。

于 2012-07-16T05:15:37.073 に答える
13

@refpの回答は、dis(逆アセンブリ)モジュールを使用したこの出力でさらにサポートされています。

>>> def a(x):
...   g = h = x
...
>>> import dis
>>> dis.dis(a)
  2           0 LOAD_FAST                0 (x)
              3 DUP_TOP
              4 STORE_FAST               1 (g)
              7 STORE_FAST               2 (h)
             10 LOAD_CONST               0 (None)
             13 RETURN_VALUE

RHS が取得されて複製され、宛先変数に左から右に格納されます (これを で試してみてくださいe = f = g = h = x)。

RHS が関数呼び出しである場合、他の一部の投稿者は混乱しています。たとえばa = b = fn()、RHS は 1 回だけ評価され、結果は連続する各変数に割り当てられます。これにより、返された値がリストや dict のように変更可能な場合、不要な共有が発生する可能性があります。

を使用しthreadingている場合は、複数の明示的な代入ステートメントに対する連鎖代入形式によって暗示される「アトミシティ」がないことに注意すると便利です。 2 つの変数に異なる値が表示される可能性があります。

ドキュメントから、7.2。代入ステートメントgおよびh2 つのターゲット リストxあり、式リストである:

assignment_stmt ::=  (target_list "=")+ (expression_list | yield_expression)

割り当てステートメントは式リストを評価し (これは単一の式またはコンマ区切りのリストであり、後者はタプルを生成することに注意してください) 、単一の結果オブジェクトを各ターゲット リストに左から右に割り当てます。

于 2012-07-16T07:35:46.967 に答える
9

OK、「連鎖割り当て」は私が求めていた検索用語でしたが、もう少し掘り下げた後、厳密には正しくないと思います。しかし、「代入文の特殊なケース」よりは検索しやすいです。

リンク先のウィキペディアの記事センダーレには、次のように書かれています。

Python では、割り当てステートメントは式ではないため、値を返しません。代わりに、連鎖割り当ては、単一の式に対して複数のターゲットを持つ一連のステートメントです。代入は左から右に実行されるため、i = arr[i] = f() は式 を評価しf()、結果を左端のターゲット に代入してから、 の新しい値を使用しiて次のターゲット に同じ結果を代入し ます。arr[i]i

別のブログ投稿は次のように述べています。

Python では、割り当てステートメントは値を返しません。連鎖割り当て (より正確には、連鎖割り当てステートメントのように見えるコード) は、割り当てステートメントの特殊なケースとして認識およびサポートされます。

これは、特に ドキュメントをよく読むと、私には最も正しいようです(target_list "=")+

割り当てステートメントは、式リスト ... を評価し、単一の結果オブジェクトを各ターゲット リストに左から右に割り当てます。

したがって、実際には「最も右から左に評価される」わけではありません.RHSが評価され、最も左のターゲットから右に割り当てられます.違い。

于 2012-07-16T06:05:04.990 に答える
4

私の無知のために、今日、pythonのChained Assignmentに噛まれました。コードで

if l1.val <= l2.val:
    tail = tail.next = l1 # this line 
    l1 = l1.next

私が期待していたのは

tail.next = l1
tail = tail.next
# or equivalently 
# tail = l1

リストに自己ループを生成する下にあるのに対し、私は無限ループに陥ります。おっと...

tail = l1
tail.next = l1 # now l1.next is changed to l1 itself

a = b = c の場合、一方向 (Python など) と同等であるため、

tmp = evaluate(c)
evaluate(a) = tmp
evaluate(b) = tmp

2 つの代入の右オペランドが等しい。

もう一方 (C++ など) に相当するもの

evaluate(b) = evaluate(c)
evaluate(a) = evaluate(b)

この場合a = b = cは基本的に

b = c
a = b

および 2 つの右側のオペランドが異なる可能性があります。

そのため、同様のコードが C++ でうまく機能します。

于 2016-04-16T14:55:54.533 に答える