简体   繁体   中英

import behavior when accessing global variables in Python

In bar.py :

var = 1
def set_var():
    global var
    var = 2

In foo.py :

from bar import *

print(var)
set_var()
print(var)

In foo2.py :

import bar

print(bar.var)
bar.set_var()
print(bar.var)

If I run foo.py the output is:

1
1

but if I run foo2.py the output is:

1
2

which is what I would expect.

I only would like to understand this behavior, since I am new to Python and haven't find a good reason for this.

PD: Additional info. I want to develop a module that uses a singleton object and I have some legacy code that uses this object. I would prefer not to prefix every reference to that object in the legacy code, so that is why I though that importing the module with the from library import object syntax would help.

So in the library I have functions that access the global object to configure it just as in the example (bar.py). And in the legacy code I hoped it only would be needed to do some kind of import as it is done in foo.py.

Thanks for the guidance.

EDITED: SECOND EXAMPLE

In bar.py

var_list = list(range(0, 2))
var_list2 = list(range(0, 2))

def set_var():
    global var_list
    var_list = list(range(0, 3))
    var_list2.append(2)

In foo.py

from bar import *

print(var_list)
print(var_list2)
set_var()
print(var_list)
print(var_list2) 

The output is:

[0, 1]
[0, 1]
[0, 1]
[0, 1, 2]

I understand that in set_var we are creating a new object with list() , but I would expect in foo.py to access this new object when I refer to it with var_list (just as it would work using the syntax bar.var_list ). I need some more background.

Thanks

"var" in bar.py is bar.var . Always (unless it's __main__.var , but that's a different issue). Any manipulation of that name happens only in/to that module and not to copies that were made any where else such as those done via from bar import ... .

There are two components to this behavior:

  1. As @Ignacio already explained, so-called "globals" in python actually have module-wide scope.

  2. A variable name in python points to an object (mutable or immutable, class or integer, it's all the same). When you assign to an existing name, you break its association with whatever it was pointing to before.

So this is what foo does:

# import
foo.var = bar.var
foo.set_var = bar.set_var

print(foo.var)
foo.set_var()   # sets bar.var
print(foo.var)

foo2 , of course, sets and prints bar.var .

Regarding your second example: You can modify a list without breaking its associations with the variables that point to it. So the changes to var_list2 are visible everywhere (note that you never assign to it). But since you assign to var_list , it behaves like var in the first example.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM