2

When I try this code in Python 2.7.3:

names = ["Paul", "Mary", "Susan"] names.sort() def valuate(string): print ord('A') return sum(ord(s) for s in string) i = 1 for name in names: print i, name, valuate(name) i += 1 

I expect the output:

65 1 Mary 409 65 2 Paul 402 65 3 Susan 522 

But instead I get:

1 Mary 65 409 2 Paul 65 402 3 Susan 65 522 

It seems the print statement outputs the i and name values before calling the function. Is that so? Why?

1

5 Answers 5

6

It's not just the print statement, it's the function call.

print i, name, valuate(name) 

Prints i, then name, then calls valuate which prints 65 (and a new line) then on return the print statement continues to print the return value (and another newline).

Sign up to request clarification or add additional context in comments.

Comments

4

The sequence of events is as follows:

print i, print name, val = valuate(name) # prints ord('A') print val 

This is confirmed by looking at the bytecodes generated for print i, name, valuate(name):

 11 19 LOAD_FAST 0 (i) 22 PRINT_ITEM 23 LOAD_FAST 1 (name) 26 PRINT_ITEM 27 LOAD_GLOBAL 1 (valuate) 30 LOAD_FAST 1 (name) 33 CALL_FUNCTION 1 36 PRINT_ITEM 37 PRINT_NEWLINE 

I don't know if this evaluation order is guaranteed (a quick search didn't reveal anything). I definitely wouldn't rely on it, and therefore wouldn't write code like this.

Comments

3

It's very simple. Your print statement evaluates the arguments lazily. It prints i first, then name, and then it calls valuate. Valuate prints 65. Then your print statement prints the result of valuate.

Comments

2

The surprise you're encountering is that the print statement prints out each of the expressions it is given before evaluating the next one. That is, a statement like print A, B, C is equivalent to:

print A, # note, the trailing comma suppresses the newline print B, print C 

As you'd expect from separate statements, A gets written out before B or C is evaluated.

That surprise is perhaps part of the reason that Python 3 has done away with the print statement in favor of a builtin print function which behaves more like you expect (all of its arguments are evaluated before the function runs).

In Python 2, you can get the Python 3 style print if you want using a future import:

from __future__ import print_function 

1 Comment

Indeed, my conceptual model of the print function was that all arguments are evaluated before the print occurs. But now I understand the way it executes and also how it will behave in the future.
0

I think that a small ',' would make things a lot more simple to grasp.

names = ["Paul", "Mary", "Susan"] names.sort() def valuate(string): print ord('A'), return sum(ord(s) for s in string) i = 1 for name in names: print i, name, valuate(name) i += 1 

Now that outputs:

1 Mary 65 409 2 Paul 65 402 3 Susan 65 522 

The comma after print makes it not to print a new line character at the end. So now you can see that valuate first prints the ord('A') and then returns the output for the outer print. (I also indented the i += 1 line)

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.