回答:
あなたは平等について比較していません。あなたはされて割り当てます。
Pythonでは、複数のターゲットに割り当てることができます。
foo, bar = 1, 2
2つの値をそれぞれfoo
とに割り当てbar
ます。必要なのは、右側にシーケンスまたは反復可能で、左側に名前のリストまたはタプルです。
あなたがするとき:
[] = ""
名前の空のリストに空のシーケンス(空の文字列はまだシーケンスです)を割り当てました。
基本的には次のことと同じです。
[foo, bar, baz] = "abc"
最終的にはfoo = "a"
、bar = "b"
およびbaz = "c"
になりますが、文字は少なくなります。
ただし、文字列に割り当てることはできないため、割り当て""
の左側では機能せず、常に構文エラーになります。
割り当てステートメントのドキュメントを参照してください。
割り当てステートメントは式リストを評価し(これは単一の式またはコンマ区切りのリストであり、後者はタプルを生成することに注意してください)、単一の結果オブジェクトを各ターゲットリストに左から右に割り当てます。
そして
ターゲットリストへのオブジェクトの割り当ては、オプションでかっこまたは角かっこで囲まれ、次のように再帰的に定義されます。
強調鉱山。
空のリストに対してPythonが構文エラーをスローしないことは、実際には少しバグです!公式に文書化された文法では、空のターゲットリストは許可されておらず、空の()
場合はエラーが発生します。バグ23275を参照してください。無害なバグと見なされます。
出発点は、これが非常に長い間存在し、無害であることを認識することです。
空のリストに割り当てても空のタプルには割り当てないのはなぜですか?も参照してください。
ドキュメントの割り当てステートメントのセクションルールに従います。
assignment_stmt ::= (target_list "=")+ (expression_list | yield_expression)
target list
がターゲットのコンマ区切りリストの場合:オブジェクトは、ターゲットリスト内のターゲットと同じ数のアイテムを持つイテラブルでなければならず、アイテムは左から右に対応するターゲットに割り当てられます。オブジェクトは、ターゲットリストのターゲットと同じ数のアイテムを含むシーケンスである必要があり、アイテムは対応するターゲットに左から右に割り当てられます。
だから、あなたが言うとき
[] = ""
""
は反復可能であり(有効なPython文字列はすべて反復可能です)、リストの要素に展開されます。
例えば、
>>> [a, b, c] = "123"
>>> a, b, c
('1', '2', '3')
空の文字列と空のリストがあるため、アンパックするものはありません。したがって、エラーは発生しません。
しかし、これを試してください
>>> [] = "1"
Traceback (most recent call last):
File "<input>", line 1, in <module>
ValueError: too many values to unpack (expected 0)
>>> [a] = ""
Traceback (most recent call last):
File "<input>", line 1, in <module>
ValueError: need more than 0 values to unpack
その[] = "1"
場合、あなたは文字列を開梱しようとしています"1"
空の変数リストにます。そのため、「アンパックするには値が多すぎます(予期される0)」という文句を言います。
同じように [a] = ""
何が本当に解凍しないようにしてケース、あなたは、空の文字列を持っていますが、あなたは、再び、可能ではない一つの変数、の上に開梱されています。そのため、「アンパックするには0を超える値が必要です」というメッセージが表示されます。
それとは別に、気づいたように、
>>> [] = ()
も()
空のタプルなので、エラーもスローしません。
>>> ()
()
>>> type(())
<class 'tuple'>
空のリストでアンパックすると、アンパックするものはありません。エラーはありません。
しかし、あなたがするとき
>>> "" = []
File "<input>", line 1
SyntaxError: can't assign to literal
>>> "" = ()
File "<input>", line 1
SyntaxError: can't assign to literal
エラーメッセージが示すように、文字列リテラルに割り当てようとしています。それは不可能です。そのため、エラーが発生します。それは言うようなものです
>>> 1 = "one"
File "<input>", line 1
SyntaxError: can't assign to literal
内部
内部的には、この割り当て操作はUNPACK_SEQUENCE
opコードに変換され、
>>> dis(compile('[] = ""', "string", "exec"))
1 0 LOAD_CONST 0 ('')
3 UNPACK_SEQUENCE 0
6 LOAD_CONST 1 (None)
ここでは、文字列が空なので、時間をUNPACK_SEQUENCE
解凍し0
ます。しかし、あなたがこのようなものを持っているとき
>>> dis(compile('[a, b, c] = "123"', "string", "exec"))
1 0 LOAD_CONST 0 ('123')
3 UNPACK_SEQUENCE 3
6 STORE_NAME 0 (a)
9 STORE_NAME 1 (b)
12 STORE_NAME 2 (c)
15 LOAD_CONST 1 (None)
18 RETURN_VALUE
シーケンス123
は、右から左にスタックにアンパックされます。したがって、スタックの一番上が、1
次が2
、最後がになります3
。次に、スタックの一番上から、左側の式の変数に1つずつ割り当てます。
ところで、Pythonでは、これにより、同じ式で複数の割り当てを行うことができます。例えば、
a, b, c, d, e, f = u, v, w, x, y, z
これが機能するのは、右側の値を使用してタプルが作成され、左側の値の上に展開されるためです。
>>> dis(compile('a, b, c, d, e, f = u, v, w, x, y, z', "string", "exec"))
1 0 LOAD_NAME 0 (u)
3 LOAD_NAME 1 (v)
6 LOAD_NAME 2 (w)
9 LOAD_NAME 3 (x)
12 LOAD_NAME 4 (y)
15 LOAD_NAME 5 (z)
18 BUILD_TUPLE 6
21 UNPACK_SEQUENCE 6
24 STORE_NAME 6 (a)
27 STORE_NAME 7 (b)
30 STORE_NAME 8 (c)
33 STORE_NAME 9 (d)
36 STORE_NAME 10 (e)
39 STORE_NAME 11 (f)
42 LOAD_CONST 0 (None)
45 RETURN_VALUE
しかし、古典的なスワッピングテクニックでa, b = b, a
は、スタックの一番上の要素の回転を使用します。あなたが唯一の二、三の要素を持っている場合、それらは特別で処理されているROT_TWO
し、ROT_THREE
代わりにタプルを構築し、開梱の指示。
>>> dis(compile('a, b = b, a', "string", "exec"))
1 0 LOAD_NAME 0 (b)
3 LOAD_NAME 1 (a)
6 ROT_TWO
7 STORE_NAME 1 (a)
10 STORE_NAME 0 (b)
13 LOAD_CONST 0 (None)
16 RETURN_VALUE
dis('[] = ""')
を呼び出さずに使用することもできますcompile()
。