What happens if you write a variable name alone in python?

953 Views Asked by At

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?

5

There are 5 best solutions below

0
On BEST ANSWER

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)

0
On

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.

1
On

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.

1
On

Nothing happens:

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

>>> baz(10, 20)
20

The statement has no effect.

0
On

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.