3

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

1

2 Answers 2

1

"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 ....

Sign up to request clarification or add additional context in comments.

4 Comments

Thanks for the response, but it is still not clear for me. I am doing a manipulation by calling to set_var, which does not raise any exception and it is equal to calling bar.set_var(). I though that from bar import would bring into the namespace all the imported objects, not to create new ones...
@Natxo.Piq: It copied the names, but it didn't rewrite the function.
For example: if var was a list, and set_var appended a new element, then, when running foo, the result would be as expected. So, behaves in a different way for mutable and non-mutable objects. Sorry, but I still don't get it. I will edit with another example.
That's because those are completely different operations.
1

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.

1 Comment

Thanks for the response. Also, this question is duplicated, but I could not find it!

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.