2013-03-06 60 views
11

只是困惑在Python全球價值,這裏有兩個代碼段爲什麼復位蟒蛇全球價值不生效

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

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

執行的結果是

$ 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 

這裏我不明白「function reset()」執行後,全局值的結果在cli.py中沒有變化(cli 2:150847672 1),但回到gl.py,全局值確實改變了!

+2

將導入更改爲'import gl'並將'a'指向'gl.a'。全局變量對於'gl'模塊來說只是全局的。您的導入製作了本地副本。 – 2013-03-06 05:54:27

+0

@Steven我也這麼認爲,但一個快速測試表明情況並非如此。來自一個相對較新的用戶也是一個很好的有趣問題 - 歡迎! – Voo 2013-03-06 05:54:48

+0

但爲什麼它必須改變?您正在導入a = 1並且它是打印1.請嘗試瞭解如何使用不可變類型以及如何工作引用和垃圾回收。你可以在Mark Lutz的書的第一部分找到所有這些,就像「乞求蟒蛇」或其他東西一樣。 – Denis 2013-03-06 06:15:03

回答

2

gl模塊導入兩次爲兩個不同的命名空間

試試這個:

import sys 
print sys.modules['__main__'].a 
print sys.modules['gl'].a 
2
共享全局變量

您在cli中導入的gl實際上是一個副本模塊對象。 如果我們改變你的代碼是這樣的:

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

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

我們得到:

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 

所以,當我們運行復位,我們改變了參考

a -> 19056568 

a -> 19056424 

但只在一個gl副本。另一個(cli中的那個)持有舊的參考。 如果我們從cli中運行gl.reset(),那麼該副本上的引用會發生變化,我們會在cli中獲得預期的變化。