Python scope, dictionary and variables difference? [duplicate] - python

This question already has answers here:
UnboundLocalError trying to use a variable (supposed to be global) that is (re)assigned (even after first use)
(14 answers)
Why isn't the 'global' keyword needed to access a global variable?
(11 answers)
Closed 6 months ago.
Python scope
I have the same question but slightly different.
number = 0
def incrementNumber():
number += 1
This one above does not work but this one below does why? Both are outside the function scope.
number = {'num':0}
def incrementNumber():
number['num'] += 1
First one works if I add the variable as global
number = 0
def incrementNumber():
global number
number += 1

Check out this blog post, it's similar to what you're doing. Specifically adam's comment.
You don't assign to dictionaryVar, you assign to dictionaryVar['A'].
So it's never being assigned to, so it's implicitly global. If you
were to actually assign to dictionaryVar, you'd get the behavior you
were "expecting".

In the first case int is not mutable, so when you do number +=1 your are really updating where number points. As you, in general, do not want changes to propagate up-scope with out
explicitly telling it to, python does a copy-on-write and gives you a local variable number. You than increment that variable and it is thrown away when the function returns
In the case of dictionaries, which are mutable, you are grabbing the up-scope reference and then mutating the underlying object, thus your addition propagates out of the function.
In the last case you have explicitly told python to not make number a local variable, thus the changes propagate out as you want.
related python closure local variables

Related

How to understand global and local scopes in Python? [duplicate]

This question already has answers here:
UnboundLocalError trying to use a variable (supposed to be global) that is (re)assigned (even after first use)
(14 answers)
Using global variables in a function
(25 answers)
Closed 5 months ago.
I am a novice in Python and wondering the situation below.
x = 1
def func():
print(x)
x = 2
return x
So I got the UnboundLocalError: local variable 'x' referenced before assignment.
But if I right understand - Python read and execute code row by row.
So in first statement inside function "print(x)" it must just relay global variable x which eq. 1, but instead I got the error.
Please explain, I think it simple.
I think your problem was explained as well in the FAQ of python docs
This is because when you make an assignment to a variable in a scope,
that variable becomes local to that scope and shadows any similarly
named variable in the outer scope. Since the last statement in foo
assigns a new value to x, the compiler recognizes it as a local
variable. Consequently when the earlier print(x) attempts to print the
uninitialized local variable and an error results.

Unbound Local Error within multiple Functions [duplicate]

This question already has answers here:
UnboundLocalError trying to use a variable (supposed to be global) that is (re)assigned (even after first use)
(14 answers)
Closed 2 years ago.
I've been creating a series of random events where each function does something different to a main set of variables, yet I keep getting unbound local errors. Here's a watered down version of the barebones of my code
variable = 1
def main():
global variable
secondary()
variable = secondary()
def secondary()
variable += 1
return variable
once again this is a really minimal way to explain my code but the variable += 1 is the part that is expressing the error
I noted all of the same issues that #TimothyChen mentioned. I'd like to explain the error you're asking about, which is:
UnboundLocalError: local variable 'v' referenced before assignment
That happens here:
v = 1
def secondary()
v += 1
The issue here is due to a behavior that is unique to Python, and a little strange (please excuse that I changed the name variable to v to avoid confusion)...
If there is a global variable declared named v, and then you only read from a variable named v inside a function, Python declares that you are reading from the global variable named v.
If there is a global variable declared named v, and then you write to a variable named v inside a function, Python says that that's a different variable local to the function unless you first say global v in that function, after which point v refers to the global variable.
So the case of your function secondary(), you are A) writing to v in the function, and B) you don't say global v anywhere in the function. So Python says that inside that function, v is a unique variable local to that function. But if v is local to the function, and your first reference to the variable in that function is:
v += 1
then v hasn't been assigned a value prior to this point. Since this line of code first reads from v, and then writes a new value back to it, you get the error you're seeing because of the attempt to read from a variable that hasn't yet been assigned a value.
It seems pretty clear that what you need to do to fix this issue is to declare your secondary function as follows:
def secondary()
global variable
variable += 1
return variable
The addition of global variable tells Python that your reference to variable is referring to the global variable with that name, even though you are writing to it.
I would suggest that in the future, you not name variables variable. That can only lead to confusion.
In the secondary function, variable isn't defined. You would have to do global variable, which would make the variable accessible. Also, you call secondary twice, which would make the variable go up twice, not sure you would want that. Furthermore, secondary doesn't have a colon after the parentheses which creates a syntax error. Lastly, the code most likely isn't indented correctly, as the secondary variable is not indented, although the other code blocks are.

Python list += unexpected behavior in inner function [duplicate]

This question already has answers here:
Is it possible to modify a variable in python that is in an outer (enclosing), but not global, scope?
(9 answers)
UnboundLocalError trying to use a variable (supposed to be global) that is (re)assigned (even after first use)
(14 answers)
Closed 2 years ago.
I read in many places that += is an in-place operation, which does not create a new list. Given this, I would expect the inner function to be able to see and mutate the lst defined in outer(). Could someone explain what is going on here? I understand there are alternative ways to make it work as expected like lst.append(2). I am just trying to understand why it does NOT work.
There is a similar question regarding += on integers UnboundLocalError with nested function scopes
That question is easy to answer as integers are immutable so ctr += 1 actually declares a new name in the inner function, and that new name is referenced before a value is assigned. This argument does not apply to the case here since += on a list does not create new bindings.
def outer():
lst = [0]
def inner():
lst += [2]
inner()
outer()
UnboundLocalError: local variable 'lst' referenced before assignment

inner function accessing outer function's variable [duplicate]

This question already has answers here:
Can you explain closures (as they relate to Python)?
(13 answers)
Closed 6 years ago.
Let's suppose to have this simple code:
def my_outer_function():
outer_var = 123
def my_inner_function():
return outer_var + 1
return my_inner_function
get_inner = my_outer_function()
get_inner()
I wonder there isn't any kind of runtime error. outer_var - the variable of the outer function - is available only when that function is running on, i.e. it vanishes when my_outer_function ends. But when I call get_inner(), my_outer_function() is already ended so I would have bet on a runtime error since my_inner_function couldn't find outer_var.
How do you explain all this?
the variable of the outer function is available only when that function is running on, i.e. it vanishes when my_outer_function ends.
That's not entirely true. The variable is available in my_outer_function's scope. my_inner_function has the scope of its own declarations and its parent's scope.
my_inner_function references a variable outside of its own scope, and so those references are bound to my_inner_function as a closure when its parent's scope is no longer available. To learn more about closures, see Can you explain closures (as they relate to Python)? (taken from Paul Rooney's comment)

When does my function will go to previous scopes to look for a variable? [duplicate]

This question already has answers here:
UnboundLocalError trying to use a variable (supposed to be global) that is (re)assigned (even after first use)
(14 answers)
Is it possible to modify a variable in python that is in an outer (enclosing), but not global, scope?
(9 answers)
Closed 6 months ago.
in python 3.0 from what i know when i'm using variables that aren't found in the local scope it will go all the way back until it reaches the global scope to look for that variable.
I have this function:
def make_withdraw(balance):
def withdraw(amount):
if amount>balance:
return 'insuffiscient funds'
balance=balance-amount
return balance
return withdraw
p=make_withdraw(100)
print(p(30))
When i insert a line:
nonlocal balance
under the withdraw function definition it works well,
but when i don't it will give me an error that i reference local variable 'balance' before assignment, even if i have it in the make_withdraw function scope or in the global scope.
Why in other cases it will find a variable in previous scopes and in this one it won't?
Thanks!
There are too many questions on this topic. You should search before you ask.
Basically, since you have balance=balance-amount in function withdraw, Python thinks balance is defined inside this function, but when code runs to if amount>balance: line, it haven't seen balance's definition/assignment, so it complains local variable 'balance' before assignment.
nonlocal lets you assign values to a variable in an outer (but non-global) scope, it tells python balance is not defined in function withdraw but outside it.

Categories