-1

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.

Damaged Organic
  • 8,175
  • 6
  • 58
  • 84
  • Yes, values are calculated before `print()` can print them out. – Martijn Pieters Nov 04 '16 at 08:07
  • It this information so common that everybody is aware and the question should be downvoted? I've read the Python docs: https://docs.python.org/3/library/functions.html#print – Damaged Organic Nov 04 '16 at 08:11
  • `a.reverse()` mutates the list in place, `list(reversed(a)))` will give you a reversed list without changing your original list. – melak47 Nov 04 '16 at 08:13
  • The downvotes might have been due to the answer to your question being self-evident. – TigerhawkT3 Nov 04 '16 at 08:14
  • `print` is just a function, values are passed, not statements. – cdarke Nov 04 '16 at 08:14
  • @KidBinary `print` is not special. – Peter Wood Nov 04 '16 at 08:14
  • @KidBinary when you say *'print outputs the wrong value'* it sounds like you think there is a bug in `print`. This is nothing to do with `print`. If you'd written your own function taking expressions you would find the same effect. – Peter Wood Nov 04 '16 at 08:16
  • No, it's just that from other languages experience, it's not that obvious for me! – Damaged Organic Nov 04 '16 at 08:23
  • 1
    This is one of the cases where python2 `print` statement differs from the use of the `print` function. The `print` statement prints what you expected, because it evaluates lazily the arguments while printing, however this is not possible with a function call. – Bakuriu Nov 04 '16 at 08:24

1 Answers1

4

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.

Community
  • 1
  • 1
Martijn Pieters
  • 1,048,767
  • 296
  • 4,058
  • 3,343