with tutorial para framework espaƱol djangoproject con applications python dictionary scope global-variables global

python - tutorial - Los diccionarios globales no necesitan palabra clave global para modificarlos?



tutorial django (2)

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

Me pregunto por qué puedo cambiar el diccionario global sin 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 yo 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


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 adopta por defecto la suposición de que es una variable local a menos que la palabra clave global ya se haya utilizado.

Sin embargo, la línea

dictvar[''key1''] += 1

No es ambiguo 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 otro tipo de objetos:

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

Es cierto siempre que se usa una operación de mutación en lugar de una de recombinación .


Puede modificar cualquier objeto mutable sin usar palabra clave global .

Esto es posible en Python porque global se usa cuando desea reasignar objetos nuevos a nombres de variables ya utilizados en el alcance 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 alcance global y los modifica.

Como dicen los docs :

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