Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Global dictionaries don't need keyword global to modify them? [duplicate]

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 
like image 302
Jovik Avatar asked Jan 14 '13 17:01

Jovik


People also ask

What is global dictionary in Python?

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.

Can you modify a dictionary?

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.

Can dictionaries be edited in Python?

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.


2 Answers

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.

like image 175
David Robinson Avatar answered Sep 27 '22 15:09

David Robinson


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   
like image 32
Ashwini Chaudhary Avatar answered Sep 27 '22 17:09

Ashwini Chaudhary