watchtower
watchtower

Reputation: 4298

assignment of variable after function definition in Python

I am new to Python so I am unsure about the difference in variable assignment before or after the function definition.

Specifically, the first example was adopted from Lutz's book.

   def tester(start):
        print("inside tester")
        def nested(label):
            print("inside nested")
            print(label,nested.state)
            nested.state += 1
            print("done with nested")

        nested.state = start
        print("done with tester")
        return nested

    F = tester(0)
    F('spam')
    F.state
    F.state

The objective of the code is to store the state information without using nonlocal.

I am unsure what nested.state means here. I am unsure because nested.state is used inside nested() function (i.e. nested.state +=1) and outside nested() function (i.e. nested.state = start).

I modified the code above to see whether Python accepts assigning variable after function declaration for nested() and to see whether there is any concept I am missing relating to function.variable call (i.e. nested.state call).

def tester(start):
    def nested(label):
        print(label, state)
        state += 1  #replaced 'nested.state' with 'state' here
    state = start   #replaced 'nested.state' with 'state' here
    return nested

F=tester(0)
F('spam')
F('ham')

Unfortunately, above code generates error local variable 'state' referenced before assignment. This tells me that I am missing some concept about function.variable (i.e. nested.state).

Can someone please help me understand three things:

I. why it is that the code with nested.state doesn't generate any error but state does?

II. what does nested.state mean? If nested.state is a mechanism to access function's variables, why is it that the call inside nested() function also uses nested.state and not state?

III. If nested.state is a mechanism to access variable inside function, then why is it that PyCharm fails to show state under dropdown when I type nested.?

I'd appreciate any help. I research SO, and couldn't find any explanation on such problems.

Upvotes: 1

Views: 1812

Answers (3)

excalibur1491
excalibur1491

Reputation: 1221

First, remember a += b is the same as a = a + b. So a must exist before getting to the +=.

Simply put, in the first example the function nested has an attribute called state (accessed by nested.state). It is an attribute, which means that once you tell nested that it has an attribute called state (you are doing this in line 9 when nested.state = start) it keep that attribute. So, in the first example nested.state exists when you get to the +=.

In the second example, you are declaring a variable called state in tester, and another variable called state in nested. The one in nested could be called potato for all that matters, because it is not the same variable. Therefore when you arrive to the +=, the variable state does not exist!

Upvotes: 0

Menglong Li
Menglong Li

Reputation: 2255

Actually, I think you're asking a question about scope in Python, ignoring your code, check this:

def scope_level_1():
    variable = 'Scope_level_1'

    def scope_level_2():
        variable = 'Scope_level_2'

        def core():
            nonlocal variable
            variable += '_TOUCHED_AND_MODIFIED_BY_CORE'
            print(variable)

        return core()

    return scope_level_2()


scope_level_1()
# 'Scope_level_2_TOUCHED_AND_MODIFIED_BY_CORE'

Don't worry about the keyword nonlocal, treat it just as a declaring to make code more readable.

Upvotes: 0

Chris
Chris

Reputation: 22953

The reason the first code example worked is because it was assigning and referencing an attribute of the nested function object. The key concept to understand here, is that Python allows you to assign new, arbitrary attributes to objects - including functions:

>>> def func(a, b):
        return a + b

>>> func(1, 2)
3
>>> func.attr = 5
>>> func.attr
5

The first code example takes advantage of this fact by using the nested function object to store the necessary state. This is the same concept as using any other object to store the state. It's particularly convenient, however, to use a function since it's readily available.

In the second example, a normal variable is used. Because of this, normal scoping rules apply which means simply that the state variable defined in tester is not the state variable being referenced in nested. Thus, an error is raised.

Upvotes: 1

Related Questions