【问题标题】:Does Python refer to the same instance in my 'from Bla import bla' statement?Python 是否在我的“from Bla import bla”语句中引用了同一个实例?
【发布时间】:2018-02-08 12:20:54
【问题描述】:

假设我有以下伪代码。在两个文件中导入bla 是指Bla 的2 个实例还是它们指的是同一个实例?换句话说,我可以在 Python 中像这样在不同的文件中连接和断开单个连接吗?

bla.py

import socket
class Bla:
  connect(self):
    self.connection = socket.socket(...)
  disconnect(self):
    self.connection.close()
bla = Bla()

hello.py

from bla import bla
bla.connect()

world.py

from bla import bla
bla.disconnect()

【问题讨论】:

  • 那将是from bla import bla,小写。你的模块文件是bla.py,而不是Bla.py

标签: python python-import python-module


【解决方案1】:

是的,在helloworld 中,bla 引用同一个实例。

模块是单例,它们的命名空间只有一个副本。第一次导入模块时,顶层语句(函数和生成器之外的所有内容)只执行一次。

模块在sys.modules mapping 中管理。首先导入确保模块已加载并存在于sys.modules 中,然后名称绑定在导入命名空间中。本质上,from bla import bla 的作用与bla = sys.modules['bla'].bla 赋值语句的作用相同。所以加载你的模块到内存只发生一次,你的bla = Bla()只执行一次,所有进一步的导入都将访问对实例的一个引用。

来自import statement documentation

基本导入语句(无from子句)分两步执行:

  1. 找到一个模块,必要时加载并初始化它
  2. 在本地命名空间中为import 语句出现的范围定义一个或多个名称。

[...]

from 表单使用稍微复杂一点的过程:

  1. 找到from子句中指定的模块,必要时加载并初始化它;
  2. 对于import 子句中指定的每个标识符:
    1. 检查导入的模块是否具有该名称的属性
    2. 如果没有,请尝试导入具有该名称的子模块,然后再次检查导入的模块的该属性
    3. 如果未找到该属性,则引发ImportError
    4. 否则,对该值的引用存储在本地命名空间中,使用as 子句中的名称(如果存在),否则使用属性名称

(我的粗体强调)。

【讨论】:

  • 请注意:如果您从两个不同的合格路径导入同一个模块,您最终可能会得到两个不同的模块实例,每个都有自己不同的 bla 对象。
  • @brunodesthuilliers:您必须为模块使用不同的名称,sys.modules 命名空间不支持重复。当bla.py 用作主脚本时,仍然会发生这种情况,并且在某处有一个import bla 语句,然后您会得到sys.modules['__main__']sys.modules['bla']
  • 我在 django 项目中也看到了这一点,其中项目根目录本身就是一个包,所以如果你在 sys.path 中同时拥有项目根目录的父路径和项目根路径并且有一个导入从项目根目录 (from myproject.someapp import something 和另一个没有项目根目录 (from someapp import something) 你最终得到两个不同的模块——这就是我所说的“不同的合格路径”(我假设你所说的“不同的名字”是什么意思) )。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2020-11-13
  • 2017-08-06
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-03-28
相关资源
最近更新 更多