Question

Suppose you have the following code.

def square(x):
    print ("Just before square returns")
    for k in dir():
        print ("{0} -------> {1}".format(k, eval(k)))
    return x*x
def cube(x):
    print ("Just before cube returns")
    for k in dir():
        print ("{0} -------> {1}".format(k, eval(k)))
    return x*x*x

x = 5
print ("cube(square({0})) = {1}".format(x, cube(square(x))))
print ("Just before main returns")
for k in dir():
    print ("{0} -------> {1}".format(k, eval(k)))

Running this code reveals the folllowing

Just before square returns
x -------> 5
Just before cube returns
x -------> 25
cube(square(5)) = 15625
Just before main returns
__builtins__ -------> <module 'builtins' (built-in)>
__cached__ -------> None
__doc__ -------> None
__file__ -------> exampleOne.py
__name__ -------> __main__
__package__ -------> None
cube -------> <function cube at 0x1037b78>
square -------> <function square at 0x1037af0>
x -------> 5

We are puzzled. Does the square function get pushed onto the stack first and have its return value computed and passed to the cube function? Another possibility is that the cube function is called first then, in the process of resolving the argument, the square function must be called. What can you tell us? Does this depend on compiler or language?

Was it helpful?

Solution

Well, of course it can depend on the language, but your example is Python.

In Python, function arguments are always evaluated before the calling the function of which they are arguments. (See the documentation.) Since square(x) is passed as an argument of cube, square is called first, and then the result is passed to cube. In other words, function calls in an expression are always evaluated "from the inside out", with the innermost ones evaluated first. This is just like the order of evaluation of mathematical expressions (innermost parentheses first).

OTHER TIPS

x= 0
def j(i):
     global x
     x+=2
     print (x)

     return i+1

def h(i):
     global x
     print (x)
     return i+1

print h(j(1))  \\prints 2,2,3

Arguments are evaluated before being passed. It's probably possible to write it so that things happen the other way but I don't know of any language which does this since it seems deeply unintuitive.

The innermost is always evaluated first, i.e it is last one who gets placed on stack.

take a look at this example:

>>> def func():
        def func1():
            print (1)
        def func2(x):
            print (2)
        def func3(y):
            print (3)
        func3(func2(func1()))


>>> func()
1                         #func1() was called first
2                         #then func2()   
3                         #last is func3() 

using dis.dis():

>>> dis.dis(func)
  2           0 LOAD_CONST               1 (<code object func1 at 0xb76aa770, file "<pyshell#19>", line 2>)
              3 MAKE_FUNCTION            0
              6 STORE_FAST               0 (func1)

  4           9 LOAD_CONST               2 (<code object func2 at 0x8a10530, file "<pyshell#19>", line 4>)
             12 MAKE_FUNCTION            0
             15 STORE_FAST               1 (func2)

  6          18 LOAD_CONST               3 (<code object func3 at 0x8a102f0, file "<pyshell#19>", line 6>)
             21 MAKE_FUNCTION            0
             24 STORE_FAST               2 (func3)

  8          27 LOAD_FAST                2 (func3)      #func3 is placed on stack
             30 LOAD_FAST                1 (func2)      #func2 gets placed on the stack
             33 LOAD_FAST                0 (func1)      #finally it's func1 that gets
                                                        # placed on stack
             36 CALL_FUNCTION            0
             39 CALL_FUNCTION            1
             42 CALL_FUNCTION            1
             45 POP_TOP                          #Removes the top-of-stack item.
             46 LOAD_CONST               0 (None)
             49 RETURN_VALUE        
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top