Ini mengikuti aturan bagian Pernyataan tugas dari dokumentasi,
assignment_stmt ::= (target_list "=")+ (expression_list | yield_expression)
Jika target list
adalah daftar target yang dipisahkan koma: Objek harus iterable dengan jumlah item yang sama karena ada target di daftar target, dan item ditetapkan, dari kiri ke kanan, ke target yang sesuai.
Objek harus berurutan dengan jumlah item yang sama dengan target di daftar target, dan item ditetapkan, dari kiri ke kanan, ke target yang sesuai.
Jadi, saat Anda berkata
[] = ""
""
adalah sebuah iterable (string python yang valid adalah sebuah iterable) dan itu sedang diurai di atas elemen-elemen dari list.
Sebagai contoh,
>>> [a, b, c] = "123"
>>> a, b, c
('1', '2', '3')
Karena Anda memiliki string kosong, dan daftar kosong, tidak ada yang perlu dibuka. Jadi, tidak ada kesalahan.
Tapi, coba ini
>>> [] = "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
Dalam [] = "1"
kasus ini, Anda mencoba membongkar string di "1"
atas daftar variabel kosong. Jadi itu mengeluh dengan "terlalu banyak nilai untuk dibongkar (diharapkan 0)".
Dengan cara yang sama, [a] = ""
jika Anda memiliki string kosong, jadi tidak ada yang benar-benar perlu dibuka, tetapi Anda mengekstraknya ke satu variabel, yang, sekali lagi, tidak mungkin. Itulah mengapa ia mengeluh "membutuhkan lebih dari 0 nilai untuk dibuka".
Selain itu, seperti yang Anda perhatikan,
>>> [] = ()
juga tidak melempar kesalahan, karena ()
merupakan tupel kosong.
>>> ()
()
>>> type(())
<class 'tuple'>
dan ketika itu dibongkar melalui daftar kosong, tidak ada yang perlu dibongkar. Jadi tidak ada kesalahan.
Tapi, saat Anda melakukannya
>>> "" = []
File "<input>", line 1
SyntaxError: can't assign to literal
>>> "" = ()
File "<input>", line 1
SyntaxError: can't assign to literal
sebagai pesan kesalahan mengatakan, Anda mencoba untuk menetapkan ke string literal. Itu tidak mungkin. Itulah mengapa Anda mendapatkan kesalahan. Ini seperti mengatakan
>>> 1 = "one"
File "<input>", line 1
SyntaxError: can't assign to literal
Internal
Secara internal, operasi penugasan ini akan diterjemahkan ke UNPACK_SEQUENCE
kode op,
>>> dis(compile('[] = ""', "string", "exec"))
1 0 LOAD_CONST 0 ('')
3 UNPACK_SEQUENCE 0
6 LOAD_CONST 1 (None)
Di sini, karena string kosong, UNPACK_SEQUENCE
buka paket 0
kali. Tetapi ketika Anda memiliki sesuatu seperti ini
>>> 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
urutannya 123
dibongkar ke dalam tumpukan, dari kanan ke kiri. Jadi, bagian atas tumpukan adalah 1
dan yang berikutnya adalah 2
dan yang terakhir adalah 3
. Kemudian menetapkan dari atas tumpukan ke variabel dari ekspresi sisi kiri satu per satu.
BTW, dengan Python, ini adalah bagaimana Anda dapat melakukan banyak tugas dalam ekspresi yang sama. Sebagai contoh,
a, b, c, d, e, f = u, v, w, x, y, z
ini berfungsi karena, nilai tangan kanan digunakan untuk membuat tupel dan kemudian akan diuraikan di atas nilai sisi kiri.
>>> 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
tetapi teknik pertukaran klasik a, b = b, a
menggunakan rotasi elemen di bagian atas tumpukan. Jika Anda hanya memiliki dua atau tiga elemen maka mereka diperlakukan dengan special ROT_TWO
dan ROT_THREE
instruksi alih-alih membangun tupel dan membongkar.
>>> 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('[] = ""')
tanpa meneleponcompile()
.