Variable scope and namespaces when using import *
Question:
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 *
?
Answers:
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!
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.
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 *
?
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!
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.