A pit in python for from module import *

  • 2020-04-02 13:53:14
  • OfStack

But there is another problem - you think you have changed a variable, but in fact, the one after the from module import * is not updated, which is very dangerous, because the program may still be able to run normally, but the result is wrong, until production is found out is more miserable.

For example:

You defined some variables in the base module:


# reference data type
class Demo:
 def __init__(self, name):
  self.name = name
demo = Demo('Demo')

# primitive type
foo = 1

Then use from in a module   The way module import reads it:


from base import *
def read():
    print 'reference data id: ' + str(id(demo))
    print 'reference data value : ' + demo.name

    print 'primitive data id: ' + str(id(foo))
    print 'primitive data value: ' + str(foo)

Write it in another module:


import base

def write():
 print "nOriginal:"
 print "Original reference data id: " + str(id(base.demo))
 base.demo.name = "Updated Demo" # this will reflect that change
 #base.demo = base.Demo("Updated Demo") # this won't relfect the change
 print "Original data id: " + str(id(base.foo))
 base.foo = 1000
 print "Original data id after assignment: " + str(id(base.foo))

Then write first, then read, to see if the content is valid:


import read
import write

print "before write"
read.read()

write.write()

print "nafter write"
read.read()

The answer is no, and the reason is:

When you use from module import, you actually copy a reference or pointer to a memory, so var and module.var both point to the same memory
When you modify module.var, you're actually making it point to a different part of memory, where var and module.var point to different parts of memory
So, even though the value of module.var has changed, the var still points to the same amount of memory, the same value
This is easy to understand for object, you can just change the value in object, this is valid, but it's not valid when you point to another object. The same is true for primitive types, because each assignment points to a different memory address, rather than inplace modifying the existing amount of memory   This is easy to verify:


In [1]: a = 10

In [2]: id(a)
Out[2]: 20429204

In [3]: a = 100

In [4]: id(a)
Out[4]: 20430108

So, the recommendation is not to use from module import * unless it is a quick and dirty script!

Example: (link: https://github.com/baiyanhuang/blog/tree/master/arena/python/from_module_import)


Related articles: