¿Los diccionarios globales no necesitan una palabra clave global para modificarlos?

Posible duplicado:
¿Por qué no se requiere la palabra clave global en este caso?

Me pregunto por qué puedo cambiar el diccionario global sin global palabra clave global . ¿Por qué es obligatorio para otros tipos? ¿Hay alguna lógica detrás de esto?

Por ejemplo, código:

 #!/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) 

Da los siguientes resultados:

 me@pc:~/$ ./globalDict.py {'key2': 2, 'key1': 1} {'key2': 2, 'key1': 2} # Dictionary value has been changed mod bar mod 

donde esperaría:

 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 

Related of "¿Los diccionarios globales no necesitan una palabra clave global para modificarlos?"

La razón es que la línea.

 stringvar = "bar" 

es ambiguo, podría estar refiriéndose a una variable global, o podría estar creando una nueva variable local llamada stringvar . En este caso, Python por defecto asume que es una variable local a menos que ya se haya usado global palabra clave global .

Sin embargo, la línea

 dictvar['key1'] += 1 

Es totalmente inequívoco. Puede referirse solo a la variable global dictvar , ya que dictvar ya debe existir para que la sentencia no arroje un error.

Esto no es específico de los diccionarios, lo mismo es cierto para las listas:

 listvar = ["hello", "world"] def listfoo(): listvar[0] = "goodbye" 

u otros tipos de objetos:

 class MyClass: foo = 1 myclassvar = MyClass() def myclassfoo(): myclassvar.foo = 2 

Es cierto siempre que se utiliza una operación de mutación en lugar de una revinculación .

Puede modificar cualquier objeto mutable sin utilizar global palabra clave global .

Esto es posible en Python porque se usa global cuando desea reasignar nuevos objetos a nombres de variables ya utilizados en el scope global o para definir nuevas variables globales.

Pero en el caso de objetos mutables, no estás reasignando nada, solo los estás modificando en el lugar, por lo tanto, Python simplemente los carga desde el ámbito global y los modifica.

Como dicen los doctores :

Sería imposible asignar a una variable global sin 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