This question already has answers here:
Why isn't the 'global' keyword needed to access a global variable?
(11 answers)
Closed 6 months ago.
cache = {}
def func():
cache['foo'] = 'bar'
print cache['foo']
output
bar
Why does this work and why doesn't it require use of the global keyword?
Because you are not assigning to cache, you are changing the dictionary itself instead. cache is still pointing to the dictionary, thus is itself unchanged. The line cache['foo'] = 'bar' translates to cache.__setitem__('foo', 'bar'). In other words, the value of cache is a python dict, and that value is itself mutable.
If you tried to change what cache refers to by using cache = 'bar' instead, you would be changing what cache points to and then you need the global keyword.
Perhaps this older answer of mine to a similar question helps you understand the difference: Python list doesn't reflect variable change.
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 1 year ago.
I believe I know the answer to this, but wanted to double-check because I find this a bit confusing.
def outerFunc():
mySet = set()
a = 0
def innerFunc():
mySet.add(1)
mySet.add(2)
a = 7
innerFunc()
print(mySet) # {1, 2}
print(a) # 0
Here, if I want to change the value of a, I need to use nonlocal. The fact that the set changes is just because sets are passed by reference? So, in an inner function we have access to the values of the outer function's variables, but cannot modify them unless they're references?
You can check the python document
In Python, variables that are only referenced inside a function are
implicitly global. If a variable is assigned a value anywhere within
the function’s body, it’s assumed to be a local unless explicitly
declared as global.
So if you assigned a variable and the variable without global just affects the local.
For example, if you assigned value to mySet, then it also does not change.
def outerFunc():
mySet = set()
def innerFunc():
mySet = {1}
mySet.add(2)
innerFunc()
print(mySet) # ''
This question already has answers here:
Why isn't the 'global' keyword needed to access a global variable?
(11 answers)
Closed 6 months ago.
cache = {}
def func():
cache['foo'] = 'bar'
print cache['foo']
output
bar
Why does this work and why doesn't it require use of the global keyword?
Because you are not assigning to cache, you are changing the dictionary itself instead. cache is still pointing to the dictionary, thus is itself unchanged. The line cache['foo'] = 'bar' translates to cache.__setitem__('foo', 'bar'). In other words, the value of cache is a python dict, and that value is itself mutable.
If you tried to change what cache refers to by using cache = 'bar' instead, you would be changing what cache points to and then you need the global keyword.
Perhaps this older answer of mine to a similar question helps you understand the difference: Python list doesn't reflect variable change.
This question already has answers here:
Why isn't the 'global' keyword needed to access a global variable?
(11 answers)
Closed 6 months ago.
cache = {}
def func():
cache['foo'] = 'bar'
print cache['foo']
output
bar
Why does this work and why doesn't it require use of the global keyword?
Because you are not assigning to cache, you are changing the dictionary itself instead. cache is still pointing to the dictionary, thus is itself unchanged. The line cache['foo'] = 'bar' translates to cache.__setitem__('foo', 'bar'). In other words, the value of cache is a python dict, and that value is itself mutable.
If you tried to change what cache refers to by using cache = 'bar' instead, you would be changing what cache points to and then you need the global keyword.
Perhaps this older answer of mine to a similar question helps you understand the difference: Python list doesn't reflect variable change.
This question already has answers here:
How do I pass a variable by reference?
(39 answers)
"Least Astonishment" and the Mutable Default Argument
(33 answers)
Closed 8 years ago.
def main():
a = [1, 2, 3]
myFunc(a)
print(a)
def myFunc(myList):
myList[1] = 100
Im studying for my final for my first compsci class about python. This code came up and I dont understand why the value of the list changes when the myFunc() doesnt have a return value. Why doesn't it just print out 1,2,3? Thank you for your time.
Python lists are mutable. Python functions pass arguments by assignment. When you call main it creates a list and associates it with the local (to main) name a. It then calls myFunc, which assigns this same list as the value of the local (to myFunc) name myList, which mutates it. (I.e., no copy of the list is made; myFunc is working with the same mutable object.) Control then flows back to main, which prints the (now changed) value of a.
I'm currently taking an intro class to Python too so I'll just try my best to answer this question.
Simply put, not all functions need to return a value.
In your function, MyFunc, you effectively changed the list without having to return a value. You just took an extra step to make your program more organized. It would be the same if you just had the contents of your function inside the main function.
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.