En Python, ¿por qué es list automáticamente global?

Este es un comportamiento extraño.

Prueba esto :

rep_i=0 print "rep_i is" , rep_i def test(): global rep_i #without Global this gives error but list , dict , and others dont if rep_i==0: print "Testing Integer %s" % rep_i rep_i=1 return "Done" rep_lst=[1,2,3] def test2(): if rep_lst[0]==1: print "Testing List %s" % rep_lst return "Done" if __name__=="__main__": test() test2() 

¿Por qué la lista no necesita declarar global? ¿Son automáticamente globales?

Me parece realmente extraño, uso la lista la mayor parte del tiempo y ni siquiera uso global para ellos como global …

Related of "En Python, ¿por qué es list automáticamente global?"

No es automáticamente global.

Sin embargo, hay una diferencia entre rep_i=1 y rep_lst[0]=1 : la anterior vuelve a vincular el nombre rep_i , por lo que se necesita global para evitar la creación de una ranura local con el mismo nombre. En el último caso, solo está modificando un objeto global existente, que se encuentra por búsqueda de nombre regular (cambiar una entrada de la lista es como llamar a una función miembro de la lista, no es un cambio de nombre).

Para probarlo, intente asignar rep_lst=[] en test2 (es decir, rep_lst=[] en una lista nueva). A menos que declare rep_lst global , los efectos no serán visibles fuera de test2 porque se crea una ranura local con el mismo nombre y se sombrea la ranura global.

Solo necesita usar global si está asignando al nombre global. Sin global , una asignación crea un nuevo local.

No hay nada especial en cómo se aplica global a una lista: global simplemente influye en el scope y la resolución de nombres.

Hay un error en Python llamado UnboundLocalError que a menudo confunde a los recién llegados. Lo confuso es que la asignación futura cambia la forma en que se busca una variable.

Cuando el intérprete ve un nombre de variable por primera vez, mira hacia adelante hasta el final del bloque de código actual, y si no tiene una asignación en algún lugar dentro del mismo bloque de código, el intérprete lo considera global. Sin embargo, si lo hace, entonces se considera local, y cualquier referencia a él antes de la asignación genera un UnboundLocalError . Ese es el error que tienes. Es por eso que necesitas declarar global rep_i . Si no asignó rep_i , no necesitaría esta línea.

Además, esto no tiene nada que ver con el tipo de variable. Además, asignar o anexar un elemento a la lista (lo que probablemente pretendía hacer, pero no lo hizo) no es asignación de la lista en sí, es esencialmente llamar a un método en un objeto de lista, que es diferente de la asignación: la asignación crea un El nuevo objeto (posiblemente con un nombre que ya existe), mientras se manipula una lista, solo cambia una lista existente. Puedes probar:

 In [1]: # It won't work with small integers, as they are cached singletons in CPython In [2]: a = 123123 In [3]: id (a) Out[3]: 9116848 In [4]: a = 123123 In [5]: id(a) Out[5]: 9116740 In [6]: # See, it changed In [7]: # Now with lists In [8]: l = [1,2,3] In [9]: id(l) Out[9]: 19885792 In [10]: l[1] = 2 In [11]: id(l) Out[11]: 19885792 In [12]: # See, it is the same In [13]: # But if i reassign the list, even to the same value In [14]: l = [2,2,3] In [15]: id(l) Out[15]: 19884272 

Si hubiera asignado un nuevo valor a rep_lst dentro de test2 (no solo a uno de sus elementos, como lo hizo), no funcionaría sin el indicador global . En Python, si no asigna una variable dentro de una función, buscará esa variable en más ámbitos globales hasta que la encuentre.

Por ejemplo, en este segmento de código, defino la lista globalmente y dentro de example() . Como la variable en example() tiene un scope más cercano al example2() que la global, es lo que se usará.

 x = ["out"] def example(): x = ["in"] def example2(): print x # will print ["in"] 

Esto no tiene nada que ver con las listas, pero es el comportamiento de cualquier variable en Python.

Aquí hay un ejemplo que demuestra que una variable no list / dict está disponible en una subrutina, y el problema es, como dice todo el mundo, el acto de rebinding a rebinding en su ejemplo de código original:

 x = 1 def test(): y = x + 1 print y test() 

Verás que esto se imprime 2 , a pesar de que x no se ha declarado global.