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

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.