Озадачен последовательностью печати при использовании вложенной печати

У меня есть некоторые проблемы с последовательностью печати Python 3 по умолчанию при вложении функции печати, которую можно упростить, как в следующем примере:

>>> def print2():
...     print('print2')
... 
>>> print('print1', print2())
print2
print1 None

Но используя эквивалент в Python 2:

>>> def print2():
...     print 'print2'
... 
>>> print 'print1', print2()
print1 print2
None

Почему последовательность печати обратная? И как я могу получить естественную последовательность в Python 3 (такую ​​же, как в Python 2), а не наоборот?

Почему вы печатаете вместо возврата строки? Аргументы функций оцениваются до того, как будет выполнена функция, так что это ожидаемое и правильное поведение.

Carcigenicate 06.04.2019 15:40

Вместо этого вы используете наверное, используя print 'print1', print2() в Python2, обратите внимание на отсутствие круглых скобок. И разница в том, что print — это оператор в Python 2, который обрабатывает каждый компонент отдельно.

Martijn Pieters 06.04.2019 15:47

@Martijn Pieters, спасибо за правильность, вы поняли! Итак, как я могу получить естественный результат последовательности в Python3?

Huan 06.04.2019 15:56

@Huan Опять же, печать внутри вызова для печати довольно странная. Вместо того, чтобы пытаться изменить порядок, было бы лучше не злоупотреблять печатью, а вместо этого передавать данные и печатать их, когда это необходимо.

Carcigenicate 06.04.2019 15:59
Почему в Python есть оператор "pass"?
Почему в Python есть оператор "pass"?
Оператор pass в Python - это простая концепция, которую могут быстро освоить даже новички без опыта программирования.
Некоторые методы, о которых вы не знали, что они существуют в Python
Некоторые методы, о которых вы не знали, что они существуют в Python
Python - самый известный и самый простой в изучении язык в наши дни. Имея широкий спектр применения в области машинного обучения, Data Science,...
Основы Python Часть I
Основы Python Часть I
Вы когда-нибудь задумывались, почему в программах на Python вы видите приведенный ниже код?
LeetCode - 1579. Удаление максимального числа ребер для сохранения полной проходимости графа
LeetCode - 1579. Удаление максимального числа ребер для сохранения полной проходимости графа
Алиса и Боб имеют неориентированный граф из n узлов и трех типов ребер:
Оптимизация кода с помощью тернарного оператора Python
Оптимизация кода с помощью тернарного оператора Python
И последнее, что мы хотели бы показать вам, прежде чем двигаться дальше, это
Советы по эффективной веб-разработке с помощью Python
Советы по эффективной веб-разработке с помощью Python
Как веб-разработчик, Python может стать мощным инструментом для создания эффективных и масштабируемых веб-приложений.
3
4
57
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Разница заключается в том, что в Python 2 print — это утверждение. Его особенность в том, что несколько выражений оцениваются слева направо, а их результат записывается сразу.

Из print справочная документация:

print evaluates each expression in turn and writes the resulting object to standard output

Таким образом, в Python 2 оператор print 'print1', print2() сначала оценивает 'print1', записывает его, затем оценивает print2(), который сам использует print для записи 'print2', а затем записывает новую строку в конце. Затем интерактивный интерпретатор Python повторяет возвращаемое значение последнего выражения, которым было None.

В Python 3 print() — это встроенный функция. Функции — это просто дополнительные выражения. Вы не можете выполнить функцию, пока не будут вычислены все выражения аргументов. Это означает, что print(...) на самом деле не выполняется до тех пор, пока все его аргументы не будут оценены, и поэтому не может ничего выводить на ваш экран, пока функция print2() не завершится и не вернет свое значение.

Таким образом, чтобы print('print1', print2()) работал, Python сначала должен оценить 'print1' (создать строковый объект), затем оценить print2() (вызвать print('print2') и вернуть None), прежде чем функция сможет быть выполнена и записать print1 None.

Вы бы получили те же результаты в Python 2, если бы использовали print('print1', print2()), потому что тогда вы фактически сначала создали бы кортеж с двумя элементами, а затем распечатали; print по-прежнему является оператором, и ('print1', print2()) оценивается как ('print1', None)print2 записывается на экран), прежде чем этот кортеж будет преобразован в строку и записан. Или вы можете использовать from __future__ import print_function в Python 2, после чего компилятор отключит оператор print, и вы также сможете использовать функцию print() в Python 2.

Решение состоит в том, чтобы использовать два вызова функции отдельныйprint() и заменить обычно написанную новую строку пробелом:

print('print1', end=' ')
print(print2())

Таким образом, 'print1' будет записано на ваш экран до того, как print2() нужно будет вызвать. Выше будет вывод

print1 print2
None

но в интерактивном интерпретаторе отсутствие новой строки немного испортило бы вывод:

>>> print('print1', end=' ')
print1 >>> print(print2())
print2
None

Но вы действительно не стали бы хочу использовать print() для записи возвращаемого значения print2(), которое есть None. Удаление лишнего print() оставит это без внимания:

print('print1', end=' ')
print2()

Если print2() отвечает за печать, не дублируйте вызовы печати.

Однако вариант Лучший относится к не печатать внутри print2(). Держите печать в центре внимания, и порядок больше не имеет большого значения. Вместо этого ваши функции возвращают строку для печати:

def result2():
    return 'print2'

print('print1', result2())

Приведенное выше выведет print1 print2 как в Python 2 (при условии, что вы используете оператор print, поэтому print 'print1', result2()), так и в Python 3.

Спасибо за ваш ответ, но оператор return завершит вложение… Я опубликовал свой реальный код, посмотрите!

Huan 06.04.2019 16:45

@Huan: в этом нет необходимости; ваш вопрос был в порядке без него. Я дал несколько советов о том, как структурировать код, вам не нужно подробно следовать ему.

Martijn Pieters 06.04.2019 16:46

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

Martijn Pieters 06.04.2019 16:47

@Huan: для этого примера мой совет остается в силе, см. gist.github.com/mjpieters/77e635326d2c9957faefc0dc6277b81f

Martijn Pieters 06.04.2019 16:51

Спасибо за ваше решение, какой я новичок! То есть нет возможности использовать функцию печати непосредственно в этом коде, так как в Python 3 последовательность печати всегда обратная?

Huan 06.04.2019 17:09

Неа. Конечно, вы можете использовать print(part1, end=' '), а затем print(part2()) для управления порядком, но здесь это не лучший вариант, потому что ваши рекурсивные вызовы функций смешивают печать и возврат значений для печати. В итоге вы печатаете много дополнительных значений None. Проблема в том, как устроен этот код, а не в print(), на самом деле.

Martijn Pieters 06.04.2019 17:29

Другие вопросы по теме