0

I'm trying to get a better understanding of python imports and namespaces. Take the example of a module testImport.py:

# testImport.py
var1 = 1

def fn1():
    return var1

if I import this like this:

from testImport import *

I can inspect var1

>>> var1
1

and fn1() returns

>>> fn1()
1

Now, I can change the value of var1:

>>> var1 = 2
>>> var1
2

but fn1() still returns 1:

>>> fn1()
1

This is different to if I import properly:

>>> import testImport as t
>>> t.var1 = 2
>>> t.fn1()
2

What's going on here? How does python 'remember' the original version of var1 in fn1 when using import *?

1
  • When you use import * you are copying the references to every variable. Each module will have it's own version. This is a major reason why you don't want to use import * Commented Jul 21, 2022 at 6:45

2 Answers 2

1

How from .. import .. works

The statement

from module import value

can basically be rewritten as

import module
value = module.value
del module # Note: this just deletes the reference to `module`. Modules are never garbage collected.

Thus, the attribute value is a copy of module.value.

Function scopes and module namespaces

If you define a function, it will be placed in a scope:

def g():
    a = 2
    def f():
        print(a)
    return f
print(g()())

The function f is bound to the namespace inside g so it can access a and print 2.

It's the same with modules. Each module has it's own scope just like a function. So functions can access variables inside their own module. Variables in different scopes, like in your case var1 won't effect it.

Why the last example works

However, you can directly modify the scope like in your last example. If you use

import module

The variable module will actually refer to the scope of the contents of that module. So you can change variables there as you wish and they will effect functions and also other files that reference that module.

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

Comments

1

The modules are two seperate namespaces. You are creating a new set of variables when you do:

from testImport import *

When you import properly, and mutate the module namespace directly,

import testImport as t
t.var1 = 2

that modifies the globals the function sees because the module global namespace is the module object namespace. They are one and the same!

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.