Huan
Huan

Reputation: 33

Puzzled at the print sequence in nesting print usage

I have some problem with Python 3's default print sequence in nesting a print function, which can be simplified as the following example:

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

But using the equivalent in Python 2:

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

Why is the print sequence reversed? And how can I yield the natural sequence in Python 3 (same as in Python 2), not reversed?

Upvotes: 3

Views: 67

Answers (1)

Martijn Pieters
Martijn Pieters

Reputation: 1124110

The difference lies in the fact that in Python 2, print is a statement. It is special in that multiple expressions are evaluated from left to right, and their result is written out immediately.

From the print reference documentation:

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

So in Python 2, the statement print 'print1', print2() first evaluates 'print1', writes that out, then evaluates print2(), which itself uses print to write out 'print2', then writes a newline at the end. The Python interactive interpreter then echoes the return value of the last expression, which was None.

In Python 3, print() is a built-in function. Functions are just more expressions. You can't execute a function until all argument expressions have been evaluated. This means that print(...) is not actually executed until all it's arguments have been evaluated, and so can't write anything out to your screen until the print2() function is done and has returned it's value.

So for print('print1', print2()) to work, Python first has to evaluate 'print1' (produces a string object), then evaluate print2() (calls print('print2') and returns None), before the function can be executed and write out print1 None.

You would get the same results in Python 2 if you used print('print1', print2()), because then you'd actually first create a tuple with two elements and that's then printed; print is still a statement, and ('print1', print2()) is evualuated to ('print1', None) (and print2 written to the screen), before that tuple is converted to a string and written out. Or you can use from __future__ import print_function in Python 2, at which point the compiler disables the print statement and you get to use the print() function in Python 2 as well.

The solution is to use two separate print() function calls, and replace the newline normally written, with a space:

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

This way, 'print1' has been written out to your screen before print2() has to be called. The above would output

print1 print2
None

but in an interactive interpreter the lack of newline would muck out the output a little:

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

But you really would not want to use print() to write out the return value of print2(), which is None there. Dropping the extra print() would leave that out:

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

If print2() is responsible for printing, don't then double up the printing calls.

The best option, however, is to not print inside print2(). Keep your printing central, and ordering doesn't matter that much any more. Have your functions return a string to be printed, instead:

def result2():
    return 'print2'

print('print1', result2())

The above would output print1 print2 in both Python 2 (provided you use the print statement, so print 'print1', result2()), and in Python 3.

Upvotes: 6

Related Questions