Search code examples
pythonscopenested-function

Python basic nested statements and scope concept


def func():
    def nested():
        global x
        x = 1
x = 2
func()
print(x)

The correct answer would be '2' and the reason why is because func() is not defined. But when I read this it seems that func() is defined as nested(). I would think that when you call func() that would then automatically call nested(). I'm struggling to grasp this and understand why I shouldn't read it that way.


Solution

  • You're defining nested inside func, but you're not calling nested() anywhere in func, so when you call func() it's effectively doing nothing.

    To do what you want try defining func as:

    def func():
        def nested():
            global x
            x = 1
        nested()
    

    UPDATE: After StevenRumbalski's comment, I think a small addition about what exactly is going on in that function can help clarify things around.

    Python's functions are themselves objects which can respond to the operator (). When you define a new function, what you're actually doing is instantiating a function object and giving it a name. In the example above, def func() creates a function instance and gives it name func, so that when you apply operator () to func (i.e. when you call the function with func()) the code of the function associated to that name is executed.

    Let's now take one step further and look at what happens with nested. Nested is defined inside func's scope, so when you exit func's scope the name nested is not defined anymore. If, however, you return the function object to the caller of func, you can use that object to run nested's code.

    A small example:

    def returning_func():
        def nested():
            print("I am nested!")
        return nested # note the lack of the () operator!
    

    In this case, if we do

    my_reference_to_nested = func()
    

    nothing gets printed, because nested is defined but not executed. If we call it, however:

    my_reference_to_nested()
    

    we execute nested's code and print to the output I am nested!