2013-03-06 3 views
11

nur verwirrt über die globalen Wert in Python, hier zwei Stück Code sindWarum Reset Python globaler Wert wirksam nicht

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

der cli Code

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

Das Ergebnis der Ausführung ist

$ 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 

Hier verstehe ich nicht nach der Ausführung von "function reset()", das Ergebnis des globalen Werts ändert sich nicht in cli.py (cli 2: 150847672 1), aber zurück zu gl.py, ändert sich der globale Wert !!

+2

Ändern Sie den Import in "gl importieren" und beziehen Sie sich auf 'a' als' gl.a'. Die globale Variable ist nur in Bezug auf das Modul "gl" global. Ihr Import erstellt eine lokale Kopie. –

+0

@Steven Das dachte ich mir auch, aber ein schneller Test zeigt, dass das nicht der Fall ist.Auch gute, interessante Frage von einem relativ neuen Benutzer - willkommen! – Voo

+0

Aber warum muss es sich ändern? Sie sind import a = 1 und es ist Drucken 1. Versuchen Sie einfach zu verstehen, wie funktioniert unveränderliche Typen und wie ist Arbeitsreferenzierung und Garbage Collection. All diese finden Sie im ersten Teil von Mark Lutz Buch genannt wie "Bitten mit Python" oder etwas Ähnliches. – Denis

Antwort

2

Ihr gl Modul importiert wird zweimal in zwei verschiedene Namensräume

versuchen Sie dies:

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

Der gl in CLI importieren ist eigentlich eine Kopie des Modulobjekt. wenn wir Code wie folgt zu ändern:

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

und

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

Wir erhalten:

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 

Wenn wir also Reset ausführen, ändern wir die Referenz

a -> 19056568 

bis

a -> 19056424 

aber nur in einer GL-Kopie. Der andere (der in CLI) hält an der alten Referenz fest. Wenn wir gl.reset() aus cli heraus aufrufen, ändert sich die Referenz auf dieser Kopie und wir erhalten die erwartete Änderung in cli.