This question already has answers here:
How do global and local variables behave in this case? [duplicate]
(3 answers)
Closed 5 years ago.
I have written a simple function to understand local and global scope in Python .
x = 50
def func(x):
print('x is', x)
x = 2
print('Changed local x to', x)
func(x)
print('x is still', x)
what I want to understand here is inside the function during x= 2 assignment whether any new variable is getting created as the globally the variable x is still holding the value 50 . How this process occurs in Python?
Yes, a new variable is created. Python's scoping rules mean that variables of the same name in different scopes are unrelated - variable references are always to the innermost scope containing a variable with that name unless this is overridden with a global statement.
Related
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 5 months ago.
If we run this code
a = 1
def foo():
b = a + 2
print(b)
foo()
it works.
But if we run this code
a = 1
def foo():
b = a + 2
print(b)
a = a + 4
print(a)
foo()
it doesn't work.
Question:
why in the first example b = a + 2 works without errors but in the second example the same line of code b = a + 2 is broken?
why if there is no reassignment of a we can get a from a global scope but if there is a reassignment we don't have an access to a even if new local a doesn't even exist yet (because the reassignment isn't finished).
Question: Why [...] the first example works without errors but in the second example the same line of code is broken?
Because in the first example, you're only reading from a global a, then writing to a local b.
In the second example, a is assumed to be a local too (since you're not declaring global a), and it has no value when you're trying to read it in the first line, hence an error.
This is similar to JavaScript's Temporal Dead Zone, if that's familiar.
As for the question in your title:
Why it's impossible to reassign global name within local scope (without global keyword) with using the global name's value in reassignment?
You're not reassigning
a global name at all in either of your examples, since indeed you're not using the global keyword. In Python, you can always read a global (or "ambient") name; otherwise it'd be a pain to e.g. use any builtin function (since they're not locals), and having a special exception for builtins would be, well, a special exception, and those aren't nice.
This question already has answers here:
How to get local variables updated, when using the `exec` call?
(3 answers)
Closed 1 year ago.
Given a string (e.g. "lista=[1,2,3]") I would like to be able to use the variable lista.
exec() does the work outside a function, but when used inside a function the variables cannot be used in that same function. I guess it has something to do with local and global variables but I don't really understand the problem.
For example,
def funcion(texto):
exec(texto)
print(lista)
funcion("lista = [3,4,5]")
Gives the error: NameError: name 'lista' is not defined.
add globals
def funcion(texto):
exec(texto, globals())
print(lista)
funcion("lista = [3,4,5]")
This question already has answers here:
Short description of the scoping rules?
(9 answers)
Closed 5 years ago.
I was thinking that variable can be only accessed after its declaration.
But apparently, Python's name resolution starts to look for from inside to outer.
My question is that this is bad practice in terms of readability? I was wondering that this might be a common knowledge for Pythonista so that I can write this kind of code from now on.
def outer():
def inner():
print x
x = ‘foo’
inner()
>>> outer()
>>> ‘foo’
When you invoke inner(), it starts executing. On line print x it sees variable name x. Then it looks to inner scope of function inner, doesn't find variable x there. Then it looks to the outer scope, namely, scope of outer. At this moment there is already variable x defined (as it is done before inner() invokation) and this variable is used.
This question already has answers here:
Global dictionaries don't need keyword global to modify them? [duplicate]
(2 answers)
Closed 8 years ago.
class blah(object):
def __init__(self):
self.x=5
blahinstance=blah()
def testclass():
blahinstance.x+=1
print blahinstance.x
testclass() #blah will be incremented
print blahinstance.x #the incremented value holds after function exit
"------------------------------------------------------------------------------------"
x=5
def test():
x+=1
print x
print x
test() #fails because ref before assignemnt
So we have read access and modify access to global variables inside a local scope, but obviously attempts at re-assignment will just create a local variable of the same name as the global variable. In the examples above, what is different about referencing the instance attribute blahinstance.x which is outside of the functions scope? To me these examples are quite similar yet one fails and one does not. We do not have a ref before assignment error with blahinstance.x despite the fact that this object is in the global scope, similar to the second example of x.
To clarify - i totally understand the second example, and global vs local scope. What I don't understand is why the first works because it seems similar to the second. Is it because the instance object and it's attribute are mutable, and we have read/modify access to globals in a local scope?
Bare names are different from attribute references.
There is no name blahinstance.x. There is a name blahinstance, and the object it refers to has an attribute called x. When you do something like blahinstance.x += 2, the only variable you're referencing is blahinstance, and you're not assigning a new value to blahinstance, so all is well. The use of x in blahinstance.x is totally "internal" to blahinstance, and x is not really a variable at all, it's just an attribute name.
The "local variable referenced before assignment" business only comes into play when you assign to a variable --- that is, a bare name --- not an attribute reference, an item reference, or anything else. In this regard blahinstance.x += 2 is no different than somelist[1] += 2; x in the first case is no more a local variable than the index 1 is in the second case.
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 8 years ago.
I have found a similar question Python variable scope error. It's related to immutable variable. But when I test mutable variable, I don't know how Python interpreter decides the scope of the variable.
Here's my sample code:
def test_immutable():
a = 1
b = 2
def _test():
print(a)
print(b)
a += 1
print(a)
_test()
def test_mutable():
_dict = {}
def _test():
print(_test.__dict__)
_dict['name'] = 'flyer'
print('in _test: {0}'.format(_dict['name']))
_test()
print(_dict['name'])
if __name__ == '__main__':
# test_immutable() # throw exception
test_mutable() # it's ok
Immutable vs mutable has nothing to do with variable scoping. Variables are just names, and always work the same way. Scoping is even decided at compile time, long before Python knows what you're going to assign to them.
The difference between your two functions is that the first one assigns directly to a with the += operator, which causes a to become a local. The second one assigns to a key inside _dict, which ultimately calls a method on the dict object, and doesn't affect the variable's scoping.