I wonder why I can change global dictionary without global
keyword? Why it's mandatory for other types? Is there any logic behind this?
E.g. code:
#!/usr/bin/env python3 stringvar = "mod" dictvar = {'key1': 1, 'key2': 2} def foo(): dictvar['key1'] += 1 def bar(): stringvar = "bar" print(stringvar) print(dictvar) foo() print(dictvar) print(stringvar) bar() print(stringvar)
Gives following results:
me@pc:~/$ ./globalDict.py {'key2': 2, 'key1': 1} {'key2': 2, 'key1': 2} # Dictionary value has been changed mod bar mod
where I would expect:
me@pc:~/$ ./globalDict.py {'key2': 2, 'key1': 1} {'key2': 2, 'key1': 1} # I didn't use global, so dictionary remains the same mod bar mod
In Python, global keyword allows you to modify the variable outside of the current scope. It is used to create a global variable and make changes to the variable in a local context.
Yes you can, dictionary is an mutable object so they can be modified within functions, but it must be defined before you actually call the function.
Modifying a value in a dictionary is pretty similar to modifying an element in a list. You give the name of the dictionary and then the key in square brackets, and set that equal to the new value.
The reason is that the line
stringvar = "bar"
is ambiguous, it could be referring to a global variable, or it could be creating a new local variable called stringvar
. In this case, Python defaults to assuming it is a local variable unless the global
keyword has already been used.
However, the line
dictvar['key1'] += 1
Is entirely unambiguous. It can be referring only to the global variable dictvar
, since dictvar
must already exist for the statement not to throw an error.
This is not specific to dictionaries- the same is true for lists:
listvar = ["hello", "world"] def listfoo(): listvar[0] = "goodbye"
or other kinds of objects:
class MyClass: foo = 1 myclassvar = MyClass() def myclassfoo(): myclassvar.foo = 2
It's true whenever a mutating operation is used rather than a rebinding one.
You can modify any mutable object without using global
keyword.
This is possible in Python because global
is used when you want to reassign new objects to variable names already used in global scope or to define new global variables.
But in case of mutable objects you're not re-assigning anything, you're just modifying them in-place, therefore Python simply loads them from global scope and modifies them.
As docs say:
It would be impossible to assign to a global variable without global.
In [101]: dic = {} In [102]: lis = [] In [103]: def func(): dic['a'] = 'foo' lis.append('foo') # but fails for lis += ['something'] .....: In [104]: func() In [105]: dic, lis Out[105]: ({'a': 'foo'}, ['foo'])
dis.dis
:
In [121]: dis.dis(func) 2 0 LOAD_CONST 1 ('foo') 3 LOAD_GLOBAL 0 (dic) # the global object dic is loaded 6 LOAD_CONST 2 ('a') 9 STORE_SUBSCR # modify the same object 3 10 LOAD_GLOBAL 1 (lis) # the global object lis is loaded 13 LOAD_ATTR 2 (append) 16 LOAD_CONST 1 ('foo') 19 CALL_FUNCTION 1 22 POP_TOP 23 LOAD_CONST 0 (None) 26 RETURN_VALUE
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