2013-03-06 14 views
11

solo confuso circa il valore globale in Python, qui ci sono due pezzi di codicePerché ripristino pitone valore globale non ha effetto

#gl.py 

import cli 

a = 1  
print "gl 1: %d %d" % (id(a), a) 


def reset(): 
    global a 
    a = 7 
    print "reset 1: %d %d" % (id(a), a) 


if __name__ == '__main__': 
    cli.handler(reset) 
    print "gl 2: %d %d" % (id(a), a) 

il codice cli

#cli.py 

def handler(func): 
    from gl import a 
    print "cli 1: %d %d" % (id(a), a) 
    func() 
    print "cli 2: %d %d" % (id(a), a) 

Il risultato dell'esecuzione è

$ python gl.py 
gl 1: 150847672 1 
gl 1: 150847672 1 
cli 1: 150847672 1 
reset 1: 150847600 7 
cli 2: 150847672 1 #Why value doesn't change 
gl 2: 150847600 7 

Qui non riesco a capire dopo l'esecuzione di "function reset()", il risultato del valore globale non cambia in cli.py (cli 2: 150847672 1), ma torna a gl.py, il valore globale cambia !!

+2

Cambiare l'importazione in 'import gl' e fare riferimento a' a' come 'gl.a'. La variabile globale è globale solo rispetto al modulo 'gl'. L'importazione esegue una copia locale. –

+0

@Steven L'ho pensato anch'io, ma un rapido test dimostra che non è così.Anche una buona domanda interessante da un utente relativamente nuovo - benvenuto! – Voo

+0

Ma perché è necessario cambiare? Si importano a = 1 e si stampa 1. Basta provare a capire come funziona i tipi immutabili e come funziona la referenziazione e la garbage collection. Intere di queste si possono trovare nella prima parte del libro di Mark Lutz chiamato "Begging with python" o qualcosa di simile. – Denis

risposta

2

Il modulo gl è importata due volte in due spazi dei nomi diversi

provare questo:

import sys 
print sys.modules['__main__'].a 
print sys.modules['gl'].a 
2

Il gl che importi in cli è in realtà una copia del file oggetto modulo. se cambiamo il codice in questo modo:

#gl.py 

import cli 
import sys 

a = 1  
print "gl 1: %d %d" % (id(a), a) 
print "gl id on import: {0}".format(id(sys.modules[__name__])) 


def reset(): 
    global a 
    a = 7 
    print "gl id in reset: {0}".format(id(sys.modules[__name__])) 
    print "reset 1: %d %d" % (id(a), a) 

def printa(): 
    print "gl: %d %d" % (id(a), a) 

if __name__ == '__main__': 
    cli.handler(reset) 
    print "gl id in main: {0}".format(id(sys.modules[__name__])) 
    print "gl 2: %d %d" % (id(a), a) 

e

#cli.py 

def handler(func): 
    #from gl import a 
    import gl 
    print "gl id in cli: {0}".format(id(gl)) 
    print "cli 1: %d %d" % (id(gl.a), gl.a) 
    func() 
    print "cli 2: %d %d" % (id(gl.a), gl.a) 
     gl.reset() 
     print "cli 3: %d %d" % (id(gl.a), gl.a) 

Otteniamo:

gl 1: 19056568 1 
gl id on import: 140075849968728 
gl 1: 19056568 1 
gl id on import: 20004096 
gl id in cli: 20004096 
cli 1: 19056568 1 
gl id in reset: 140075849968728 
reset 1: 19056424 7 
cli 2: 19056568 1 
gl id in reset: 20004096 
reset 1: 19056424 7 
cli 3: 19056424 7 
gl id in main: 140075849968728 
gl 2: 19056424 7 

Così, quando si corre di reset, cambiamo il riferimento

a -> 19056568 

a

a -> 19056424 

ma solo in una sola copia. L'altro (quello in cli) tiene il vecchio riferimento. Se eseguiamo gl.reset() dall'interno di cli, il riferimento su quella copia cambia e otteniamo il cambiamento previsto in cli.

Problemi correlati