Відповіді:
Ви не порівнюєте за рівність. Ви призначаєте .
Python дозволяє призначити кілька цілей:
foo, bar = 1, 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
оп-код,
>>> 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
. Потім він присвоює зверху стека змінні з виразу лівої сторони по черзі.
BTW, в 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()
.