Question

Recently I became curious about but what happens in line 2 of the following bogus python code:

def my_fun(foo,bar):
    foo
    return foo + bar

The reason I became interested is that I'm trying Light Table and tried to put a watch on "foo." It appeared to cause the python interpreter to hang.

Am I correct in thinking that this line has absolutely no effect and does not cause any sort of error? Can someone explain what the interpreter does exactly here?

Was it helpful?

Solution

One can look at what is happening with a little help from the built-in dis module:

import dis

def my_fun(foo,bar):
    foo
    return foo + bar

dis.dis(my_fun)

The dis.dis function disassembles functions (yep, it can disassemble itself), methods, and classes.

The output of dis.dis(my_fun) is:

  4           0 LOAD_FAST                0 (foo)
              3 POP_TOP

  5           4 LOAD_FAST                0 (foo)
              7 LOAD_FAST                1 (bar)
             10 BINARY_ADD
             11 RETURN_VALUE

The first two bytecodes are exactly what we need: the foo line.

Here's what these bytecodes do:

  1. The first one pushes a reference to a local variable foo onto the stack (LOAD_FAST)
  2. The second one removes the top of the stack (POP_TOP)

Basically, foo line has no effect. (well, if foo variable is not defined then LOAD_FAST will throw the NameError)

OTHER TIPS

Nothing happens. It becomes equivalent to a pointless operation Looking at the dis output

In [3]: dis.dis(my_fun)
  2           0 LOAD_FAST                0 (foo)
              3 POP_TOP             

  3           4 LOAD_FAST                0 (foo)
              7 LOAD_FAST                1 (bar)
             10 BINARY_ADD          
             11 RETURN_VALUE 

We can see that it does the load fast for foo then does nothing with it.

Try it at the command line: it just returns the value in foo. This doesn't mean it can't have side effects in some special cases: if you do something like:

def my_fun(foo, bar):
    foo.prop
    return foo.func(bar)

even though technically we have just returned the value, if it's defined as a property then foo.prop can actually call a function.

But normally... you wouldn't do this in modules, only in an interactive console.

The foo statement is an example of expression statement, so it gets evaluated when the interpreter meets it.

An expression statement evaluates the expression list (which may be a single expression).

So foo is loaded, the expression is evaluated (which is foo itself, so no further actions are needed) and the result is forgotten immediately.

Nothing happens:

>>> def baz(foo, bar):
    foo
    return bar

>>> baz(10, 20)
20

The statement has no effect.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top