2011-06-13 14 views
8

Este es un comportamiento extraño.En Python, ¿por qué la lista [] es automáticamente global?

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é lista no es necesario declarar global? ¿son automáticamente globales?

Me parece muy extraño, i lista utilizan la mayor parte del tiempo y que incluso no uso global en absoluto para nosotros como mundial .....

Respuesta

12

No es automáticamente global.

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

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

5

Sólo tiene que utilizar global si está asignando a el nombre global. Sin global, una tarea crea un nuevo local.

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

+0

Entonces, ¿eso significa que si agrego algo a la lista, fallará? voy a tratar. –

+0

añadiendo algo a rep_lst no falla, estoy confundido .. –

+1

No, no fallará. Es solo si asigna el nombre global, lo que se conoce como volver a vincular. Entonces 'rep_lst = []' creará una nueva lista y le vinculará una nueva variable local. Pero 'rep_lst.append()' buscará el nombre 'rep_lst', lo encontrará en el espacio de nombre global y llamará a un método sobre él. –

2

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

Por ejemplo, en este segmento de código, defino la lista tanto globalmente como dentro de example(). Dado que la variable en example() tiene un alcance más cercano a example2() que la global, es lo que se utilizará.

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.

3

Hay un error en python llamado UnboundLocalError que a menudo confunde a los recién llegados. Lo confuso es: futuro asignación hace cambiar la forma en que se busca una variable.

Cuando el intérprete ve un nombre de variable por primera vez, mira hacia el final del bloque de código actual, y si no tiene una asignación en cualquier lugar dentro del mismo bloque de código, el intérprete lo considera global. Si lo hace, sin embargo, 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 necesita 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 agregar un elemento a la lista (lo que probablemente pretendía hacer, pero no lo hizo) no es la asignación de la lista, básicamente se trata de llamar a un método en un objeto de lista, que es diferente de la asignación: la asignación crea un nuevo objeto (posiblemente bajo un nombre que ya existe), mientras que la manipulación de una lista simplemente cambia una lista existente. Usted puede tratar de:

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 
2

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

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

verá este imprime 2, a pesar de no haber sido declarado x global.

+0

Muchas gracias, eso explica mucho! +1 –

Cuestiones relacionadas