Функция печати Python не возвращает обновленную переменную - PullRequest
0 голосов
/ 11 декабря 2018

Я изучаю Python, и что-то связанное с print смутило меня.Не уверен, что кто-то уже задавал тот же вопрос:

>>> x = 1
>>> x, y = x + 2, print(x)
1

Я понимаю, что вывод 1 является побочным эффектом функции print Python.Но почему он не печатает 3?Я ожидал 3, потому что x обновляется во второй строке?Я думал, что это эквивалентно (очевидно, неправильно):

>>> x = 1
>>> x = x + 2
>>> x
3
>>> y = print(x)
3

Я хотел бы понять логику этой функции print.Почему он не печатает обновленное значение x?

Я новичок в мире программирования, поэтому любая информация очень ценится!

Ответы [ 4 ]

0 голосов
/ 11 декабря 2018

Значение в левой части присвоения не обновляется, пока не будет обработана вся правая часть. Поэтому X еще не равен 3, когда вы пытаетесь напечатать его в правой части.

0 голосов
/ 11 декабря 2018
>>> x = 1
>>> x, y = x + 2, print(x)
1

print(x) выводит значение, сохраненное в x, назначенном вами

для печати 3, вам нужно напечатать (y)

, так как y хранит значение x + 2

0 голосов
/ 11 декабря 2018

Поскольку python обрабатывает построчно (имеется в виду после всей строки, обрабатывает его), поэтому x еще не обновился, поэтому он работает не так, как ожидалось, но если вы сделаете ; (точка с запятой), тобудет работать, потому что точка с запятой ; в основном тоже является разделителем строк, поэтому в основном все, что после ; берется в качестве новой строки, демо:

>>> x=1
>>> x, y = x + 2,0; print(x)
3
>>> 

Проблема в том, что y будет0:

>>> y
0
>>> 

Поскольку я делаю это, у вас должно быть значение

Но если вам все равно, удалите его:

>>> x=1
>>> x, y = x + 2,0; print(x)
3
>>> del y
>>> y
Traceback (most recent call last):
  File "<pyshell#12>", line 1, in <module>
    y
NameError: name 'y' is not defined
>>> 
0 голосов
/ 11 декабря 2018

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

>>> import dis
>>> dis.dis('x, y = x + 2, print(x)')
  1           0 LOAD_NAME                0 (x)
              2 LOAD_CONST               0 (2)
              4 BINARY_ADD
              6 LOAD_NAME                1 (print)
              8 LOAD_NAME                0 (x)
             10 CALL_FUNCTION            1
             12 ROT_TWO
             14 STORE_NAME               0 (x)
             16 STORE_NAME               2 (y)
             18 LOAD_CONST               1 (None)
             20 RETURN_VALUE
>>>

Примечание, x + 2 и print(x) оцениваются сначала .BINARY_ADD и CALL_FUNCTION появляются перед двумя STORE_NAME s.

Обратите внимание, вы можете думать об этом как об эквивалентном построении кортежа:

temp = (x + 2, print(x))

, а затем просто:

x, y = temp

Тем не менее, обратите внимание, что в соответствии с disasembler фактический промежуточный кортеж не создается.Стек вызовов используется для хранения промежуточных значений.Это оптимизация компилятора.Однако оптимизация не работает для кортежей, длина которых превышает 3, поэтому, используя 4, вы увидите, что промежуточный кортеж создает:

>>> dis.dis('foo, bar, baz, bang  = bang, baz, bar, foo')
  1           0 LOAD_NAME                0 (bang)
              2 LOAD_NAME                1 (baz)
              4 LOAD_NAME                2 (bar)
              6 LOAD_NAME                3 (foo)
              8 BUILD_TUPLE              4
             10 UNPACK_SEQUENCE          4
             12 STORE_NAME               3 (foo)
             14 STORE_NAME               2 (bar)
             16 STORE_NAME               1 (baz)
             18 STORE_NAME               0 (bang)
             20 LOAD_CONST               0 (None)
             22 RETURN_VALUE
>>>

Обратите внимание на BUILD_TUPLE и UNPACK_SEQUENCE, то естьОбщий способ, что распаковка работает в Python.Просто компилятор оптимизирует общие случаи двух или трех с помощью операционных кодов ROT_TWO и ROT_THREE.

Обратите внимание: поскольку правая часть вычисляется первой, это позволяет работать идиоме подкачки Python!

x, y = y, x

Если бы это было эквивалентно:

x = y
y = x

Вы бы потеряли значение для x вместо замены!

...