11

Just confused about global value in Python, here are two piece of code

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

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

The result of execution is

$ 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

Here I don't understand after "function reset()" execution, the result of global value doesn't change in cli.py(cli 2: 150847672 1), but back to gl.py, global value does change!!

linbo
  • 2,393
  • 3
  • 22
  • 45
  • 2
    Change import to `import gl` and refer to `a` as `gl.a`. The global variable is only global with respect to the `gl` module. Your import makes a local copy. – Steven Rumbalski Mar 06 '13 at 05:54
  • @Steven I thought so too, but a quick test shows that that's not the case. Also good, interesting question from a relatively new user - welcome! – Voo Mar 06 '13 at 05:54
  • But why it's must change? You are import a=1 and it's print 1. Just try understand how works immutable types and how is work referencing and garbage collection. Whole of these you can find in the first part of Mark Lutz book called like "Begging with python" or something the same. – Denis Mar 06 '13 at 06:15

3 Answers3

4

Two concepts are missing here

  • Globals are globals to modules and not across modules

Refer: http://legacy.python.org/doc/essays/ppt/hp-training/sld036.htm

Refer: http://docs.python.org/release/2.4/ref/global.html

  • Variables are imported as Values and not by reference

Refer: https://stackoverflow.com/a/3338357/977038

If you need to share Global variables across modules refer How do I share global variables across modules?

Community
  • 1
  • 1
Abhijit
  • 62,056
  • 18
  • 131
  • 204
2

Your gl module is imported twice into two different namespaces

try this:

import sys
print sys.modules['__main__'].a
print sys.modules['gl'].a
John La Rooy
  • 295,403
  • 53
  • 369
  • 502
2

The gl you import in cli is actually a copy of the module object. if we change your code like this:

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

and

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

We get:

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

So when we run reset, we change the reference

a -> 19056568

to

a -> 19056424

but only in one gl copy. The other one (the one in cli) holds on to the old reference. If we run gl.reset() from within cli, the reference on that copy changes and we get the expected change in cli.

nat
  • 184
  • 1
  • 4