Python中不同模块 import 同一个模块中的一个对象的时候,都是同一个对象吗?

假设我在模块 base 中定义了一个对象 obj, 然后在模块 a, bcimport 了对象 obj.

然后我在模块 a 中对 obj 进行了修改, 模块 bc 中的 obj 会产生相应的修改吗?为什么?

阅读 5.5k
3 个回答

我给你做个简单示例(环境:Python shell 3.6.5)

step1: 编写t.py,保存在桌面。

clipboard.png

step2: 启动shell,添加桌面的path。

clipboard.png

step3: import t并调用test函数。

clipboard.png

step4: 修改源文件,并尝试再次调用。

clipboard.png
clipboard.png
可以看到,输出与修改之前相同的内容。这个原因,和你各个py文件之间的调用原理是相同的,那原因是什么?

原因:
python有它的垃圾回收机制,恰巧的是,它以引用计数为主。所以之前运行的py文件还在本次调用中(只要我不关闭shell),引用计数为1,所以如果在不引入imp模块的reload重新载入,引用计数就不会到0,就还会输出修改之前的内容。

希望能让你理解.

  • 模块 base:

    num = 10  # 数值类型
    lst = [0]  # 引用类型
  • 模块 a:

    from base import num, lst  # 直接导入
    
    num = 100
    lst.append('a')
  • 模块 b:

    import base  # 通过模块调用
    
    base.num = 100
    base.lst.append('b')
  • 执行脚本 run.py:

    import base
    
    print(base.num, id(base.num))
    print(base.lst, id(base.lst))
    print('--------------------')
    
    import a
    
    print(a.num, id(a.num))
    print(a.lst, id(a.lst))
    print(base.num, id(base.num))
    print(base.lst, id(base.lst))
    print('--------------------')
    
    import b
    
    print(base.num, id(base.num))
    print(base.lst, id(base.lst))
  • 运行结果:

    10 1578461456
    [0] 37413272
    --------------------
    100 1578462896
    [0, 'a'] 37413272
    10 1578461456
    [0, 'a'] 37413272
    --------------------
    100 1578462896
    [0, 'a', 'b'] 37413272

可以看到, 通过 from base import num, lst 的方式导入的 num, lst, 在修改后, num 的修改没有反馈到 base, 而 lst 的修改反馈到了 base.

通过 import base 的方式修改 num, lst, 两者的修改都反馈到了 base.

简单的结论:

  • 通过 from xxx import xxx 的方式导入的对象, 如果是 数值对象 的话, 相当于是在当前模块创建了一个同名对象, 并将值赋给这个同名对象。 如果是 引用对象 的话, 相当于是在当前模块创建了一个对该对象的引用。 当前模块做的修改会反馈到原模块。
  • 通过 import xxx 的方式导入模块, 然后用 module.xxx 的方式对模块内的对象进行调用或修改, 结果会反馈到原模块。

如一楼, 修改模块文件的话, 不会相应修改
如果要相应修改需要重新加载

————————————————华丽的分割线————————————————

另外一种会修改的栗子:

# m_base.py
num = 1
myList = [1]
# m_a.py
import m_base
import threading


def doChange():
    print('do change')
    m_base.num = 2
    m_base.myList[0] = 2


timer = threading.Timer(5, doChange)
timer.start()
# m_b.py
import time
import m_base


def printBase():
    while 1:
        print('b num:', m_base.num)
        print('b list:', m_base.myList[0])
        print('')
        time.sleep(1)


printBase()
# m_all.py
import m_a
import m_b

执行python m_all.py:

clipboard.png

因为这里实际就是同一个对象

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题