Kid Binary Kid Binary - 1 month ago 14
Python Question

Python print() calculates expressions ahead of output

The thing I've noticed is that

print()
is sometimes outputs final calculated value when multiple statements are printed. To illustrate:

a = [1, 2, 3]
print(a, a.reverse(), a)


Output is
[3, 2, 1] None [3, 2, 1]
, but shouldn't the first output of
a
be
[1, 2, 3]
?

If prints are separated, say:

a = [1, 2, 3]
print(a, end=' ')
print(a.reverse(), a)


The output gives correct
[1, 2, 3] None [3, 2, 1]
.

This behavior caused me a couple of hard minutes trying to figure out the bug. I've searched all around for the answer, but supposedly I'm looking in the wrong direction.

Is this because values are calculated before
print()
? In if so, why?




UPDATE:

I've asked the question because from other languages experience the reason of this isn't so obvious for me. For example, PHP:

$a = [1, 2, 3];
var_dump(
$a, array_pop($a), $a
);


Produces output without pre-executing expressions:

array(3) {[0]=>int(1) [1]=>int(2) [2]=>int(3)}
int(3)
array(2) {[0]=>int(1) [1]=>int(2)}


While question might be stupid, I don't see any more answers to it around except for this one on SO.

Answer

When you call a function (and print() is no more than a function here), Python has to execute all the expressions that form the arguments first. The results of those expressions are then passed into the function call.

Moreover, referencing an object by name does not pass in a copy of that object, you pass in the object itself. Since a references a list, you are passing in that list, not another list that is a copy of the first.

So in the first example, the results of the expressions a, a.reverse() and a are sent to the print() function. Because a.reverse() alters a list in place, you just sent the very same list to the print() call twice, after that list has been reversed. Both a expressions result in the same list, that has been reversed, being passed to print().

In the second example, you first send in the a list, the print() function writes it out, and then in a second print() call, you reverse that list and pass it in to be printed again.

I've got the impression you are perhaps most confused about how Python treats names and how parameters are passed into a function call. I recommend you read up on these with:

If you wanted to pass in a copy of the list that contains the same elements in reverse order, you would have to do so explicitly. You can use either a[::-1] or list(reversed(a)) to produce such a copy.

Comments