I am a beginner in Python and using Mark Lutz's book to learn the fundamentals of Python.
Here's an example that the author uses to demonstrate storing state information using lists:
def tester(start):
def nested(label):
print(label,state[0])
state[0] += 1
state = [start]
return nested
Here's the code to test state information:
F = tester(3)
F('sam')
F('sam')
You would see that the counter increases from 3 and then continues. In essence, above code stores initial state start (passed during initialization of the object) in [state] and increments it every time label is called.
However, I am unsure why Python doesn't throw an error in nested block. Specifically, [state] is local to tester and not nested.
To demonstrate what I mean, I am going to replace state[0] by state.
def tester(start):
def nested(label):
print(label,state) #Replaced state[0] with state
state += 1 #Replaced state[0] with state
print("after:",state)
state = start #Replaced state[0] with state
return nested
Technically, above code should also work fine because all I have done is that replaced the list with the variable. However, PyCharm wouldn't even run this code. I get an error nboundLocalError: local variable 'state' referenced before assignment
Can someone please explain why the version with list works fine? The author has stated that "this leverages the mutability of lists, and relies on the fact that in-place object do not classify a name as local."
I am not really sure what that means. Can someone please help me? Thanks for any help extended to me.
You should read this section of the documentation.
Basically, in both versions the scope of the nested block allows it to interact with the namespace of the encompassing block. The difference is that you are not reassigning state in the first example, you're mutating it.
In the second example, Python knows that you are going to assign a value to that reference later in the function, so it is treated as a name from the local nested namespace, rather than the outer tester namespace.
You can use the nonlocal keyword to circumvent this and use the other reference from the other namespace
def tester(start):
def nested(label):
nonlocal state
print(label,state)
state += 1
print("after:",state)
state = start
return nested
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With