Что называется этим назначением в Python? a = b = True - программирование
Подтвердить что ты не робот

Что называется этим назначением в Python? a = b = True

Я знаю о распаковке кортежей, но что это за назначение называется, где у вас есть несколько знаков равенства на одной строке? a la a = b = True

Он всегда меня немного подстраивает, особенно когда RHS изменен, но у меня возникают реальные проблемы с поиском правильных ключевых слов для поиска в документах.

4b9b3361

Ответ 1

Это цепочка заданий, а термин, используемый для описания, это...

- Могу ли я получить барабан, пожалуйста?

Назначение цепочки.


Я просто дал ему довольно google-прогон и обнаружил, что читать эту тему не так много, возможно, потому что большинство людей считают это очень прямолинейным (и только настоящие вундеркинды хотели бы узнать больше о тема).


В предыдущем выражении порядок оценки можно рассматривать как начинающийся с самого правого = и затем работающий влево, что эквивалентно написанию:

b = True
a = b

Вышеуказанный порядок - это то, что большинство языков описывает цепочку назначений, но python делает это по-другому. В python выражение оценивается как эквивалентное ниже, хотя оно не приведет к каким-либо другим результатам, кроме того, что было описано ранее.

temporary_expr_result = True

a = temporary_expr_result
b = temporary_expr_result

Дополнительное чтение доступно здесь в stackoverflow:

Ответ 2

ОК, "прикованное назначение" было поисковым термином, которым я был, но после немного большего количества копания я думаю, что это не совсем правильно. но его легче искать, чем "особый случай оператора присваивания".

Статья в Википедии senderle связана с сообщением:

В Python операторы присваивания не являются выражениями и, следовательно, не верните значение. Вместо этого, цепочки назначений - это серия операторов с несколькими целями для одного выражения. присваивания выполняются слева направо, так что i = arr[i] = f()оценивает выражение f(), затем присваивает результат самому левому target, i, а затем присваивает тот же результат следующей цели, arr[i], используя новое значение i.

Другое сообщение в блоге:

В Python операторы присваивания не возвращают значение. Прикованный присваивание (или, точнее, код, который выглядит как привязанное присвоение заявления) признается и поддерживается как частный случай присваивание.

Это кажется мне самым правильным, при более близком чтении документов - в частности (target_list "=")+ - которые также говорят

Оператор присваивания вычисляет список выражений... и присваивает единственный результирующий объект для каждого из целевых списков, слева направо вправо.

Таким образом, это не действительно "оценивается с самого правого налево" - оценка RHS оценивается, а затем назначается с левой стороны цели вправо - не то, что я могу думать о каких-либо реальных (или даже надуманных) примерах, где это будет иметь значение.

Ответ 3

@refp answer дополнительно поддерживается этим выходом с помощью модуля 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 оценивается только один раз, а затем результат присваивается каждой последовательной переменной. Это может привести к нежелательному совместному использованию, если возвращаемое значение является изменяемым, например, списком или dict.

Для тех, кто использует threading, полезно отметить, что не существует "атомарности", подразумеваемой цепной формой присваивания по нескольким явным операторам присваивания - может существовать переключатель потоков между назначениями на g и h, а другой поток глядя на них, они могли видеть разные значения в двух переменных.

Из документации, 7.2. Заявления присваивания, g и h являются двумя целевыми списками, x является списком выражений:

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

Оператор присваивания оценивает список выражений (помните, что это может быть одно выражение или список, разделенный запятыми, последний из которых имеет кортеж) и присваивает единственный результирующий объект каждому из целевых списков слева направо.

Ответ 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

тогда как я получил ниже, которые производят цикл self в списке, оставьте меня в бесконечном цикле, кричит...

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

и имеют равный правый операнд для двух присваиваний.

другой (например, С++), эквивалентный

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

так как в этом случае a = b = c в основном

b = c
a = b

и два правых операнда могут быть разными.

Вот почему аналогичный код хорошо работает на С++.