48、Python之模块和包:当导入模块时,Python解释器做了什么

news2024/11/20 0:08:57

引言

上一篇文章中,我们简单介绍了各种导入模块的方法,并通过代码演示了模块被导入之前的模块查找的路径解析过程,但是,只是局限在了加载模块之前。

今天这篇文章,打算把整个模块导入的全流程进行梳理,从而更清晰地理解模块导入的过程中,Python解释器做了哪些动作,到底发生了什么。

本文的主要内容有:

1、Python中的两大模型

2、命名空间

3、模块导入的全过程及底层细节

Python中的两大模型

在前面的文章中,我们已经多次提到,程序 = 数据结构 + 算法,或者表述为:程序 = 数据的表达 + 数据的处理。而对应到Python中,就是两大模型:数据模型(Data Model)和执行模型(Execution Model)

数据模型,我们前面已经反复提及,概括来说,就是“一切皆对象”。每个对象都有其id(粗略理解为地址)、内容(对象相关的属性、方法)、类型(type)。

由“一切皆对象”,进而得出函数、类、模块、包也都是对象,自然在Python中也都是一等公民。

执行模型,其实就是通过代码,对数据模型进行读与写,也就是对对象的读与写。要对对象进行读写,我们一般是通过变量名进行的,所以,执行模型的一个核心概念,就是“名称绑定”,也就是将每一个变量名与一个对象进行绑定。在Python中变量名是“标签”而非“盒子”的观点,在前面的文章中已经有所提及,不太理解的,可以翻一下之前的文章。

由于变量是贴在对象上的“标签”,变量名与对象的绑定关系,可以是“多对一”的关系。

执行模型中,一个代码块能够读写的对象,是能够访问到的名称绑定的对象。这些名称和对象的绑定被放到了一个称为“命名空间”的结构中,命名空间可以理解为是一个字典。

所以,执行模型,也可以这样表述为“代码块在命名空间上的执行,对命名空间中的名称所绑定的对象进行读写操作”

执行模型中,代码块能够执行,名称绑定是前提,但是,能够执行,还需要能够进行名称解析,以及特殊情况下名称绑定的解绑操作。

其中,名称的解析,就涉及到了“作用域”的概念,之前已经介绍过LEGB的规则,这里就不展开了。

e00179a9a67a4b82cb2adba617364746.jpeg

之所以介绍执行模型,主要是由于当导入模块时,会对命名空间产生影响。

命名空间

命名空间(namespace)是编程语言中一个很核心的概念,用于组织代码、避免命名冲突。在Python中,命名空间本质上是一个从名称(变量名)到对象的映射关系的绑定,也就是命名空间中记录了变量名、函数名、类名等与实际对象的关联关系。

在Python中,命名空间可以分为四类,分别是:局部命名空间(Local Namespace)、闭包命名空间(Enclosing Namespace)、全局命名空间(Global Namespace)和内置命名空间(Built-in Namespace)。

1、局部命名空间:包含函数和方法内定义的变量和参数,每次函数调用都会创建一个新的局部命名空间。

2、闭包命名空间:包含在嵌套函数中的外层函数中的局部命名空间。

3、全局命名空间:包含当前模块中定义的所有全局变量、函数、类等,当模块被导入时,Python解释器会创建一个全局命名空间。

4、内置命名空间:包含Python解释器启动时加载的内置函数、异常等。比如,print()、len()、int等都在内置命名空间中。

每种命名空间都有自己的生命周期:

1、局部命名空间:从函数调用开始到函数返回结束。

2、闭包命名空间:从外层函数被调用到内层函数执行结束。

3、全局命名空间:从模块被导入或者脚本开始执行到脚本结束。

4、内置命名空间:从Python解释器启动到解释器进程结束。

在Python中,有3个内置函数,可以查看命名空间中的内容:

1、globals():查看当前全局命名空间的字典

2、locals():查看当前局部命名空间的字典

3、dir():返回当前代码所在范围的所有名字列表

模块导入的全过程及底层细节

有了前面关于“执行模型”和“命名空间”的概念,可以帮助我们更好地理解Python中的模块导入。

首先来看下模块导入的全过程:

1、查找模块

当执行import 模块名等类似的操作时,Python解释器首先会在sys.modules字典中查找,如果已经存在,直接使用缓存的模块,避免重复加载。

如果sys.modules模块中不存在,则会检查是否是内置模块,这些模块是C语言编写的,并被编译到了Python解释器中。

如果不是内置模块,Python解释器会在sys.path列表中按顺序进行模块的查找。关于路径的查找顺序,上一篇文章中已经提及,可以自行查阅。

2、编译模块

如果是首次导入,找到的是一个.py文件,Python解释器会将其“编译”为字节码(.pyc)文件,以提高后续执行的加载速度。如果已经存在编译后的字节码文件且没有过期(可以理解为比较.py文件的修改时间与.pyc文件的生成时间),则会直接加载字节码文件。

3、执行模块代码

一旦模块的字节码被加载,Python解释器会创建一个新的模块对象,并执行模块的顶级代码(即未包裹在函数定义或者类定义中的代码)。在执行模块代码时,Python解释器首先会为该模块创建一个独立的全局命名空间,模块中的顶级代码是在该独立的全局命名空间中执行的。

4、更新命名空间

执行完模块的顶级代码后,模块对象会被添加到sys.modules字典中,以便将来可以复用,并且导入的模块名会绑定到当前作用域中的模块对象(根据导入方式的不同,除了模块名与模块对象的绑定之外,还可能涉及到模块中变量、函数等的绑定)

总结

为了更好地理解Python中模块导入的过程及细节,本文首先回顾了Python中的数据模型,然后引入了执行模型的概念。之后,简单介绍了Python中的命名空间,4种命名空间的含义及其生命周期。基于执行模型及命名空间的概念,对Python中的模块导入全过程做了一个系统性的梳理。

在下一篇文章中,将通过实际的代码执行,验证一下Python模块导入、加载的过程。

感谢您的拨冗阅读,如果对您学习Python有所帮助,欢迎点赞、关注。

2d34713a99a6b09b3b59a38b5bee870c.jpeg

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2065542.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Windows上传Linux文件行尾符转换

Windows上传Linux文件行尾符转换 1、Windows与Linux文件行尾符2、Windows与Linux文件格式转换 1、Windows与Linux文件行尾符 众所周知,Windows、Mac与Linux三种系统的文件行尾符不同,其中 Windows文件行尾符(\r\n): L…

【初阶数据结构题目】40. 计数排序

计数排序 计数排序又称为鸽巢原理,是对哈希直接定址法的变形应用。 操作步骤: 统计相同元素出现次数 根据统计的结果将序列回收到原来的序列中 思路: 例如:{6,1,2,9,4,…

书生模型实战L1---OpenCompass 评测

书生模型实战系列文章目录 第一章 入门岛L0(Linux) 第二章 入门岛L0(python) 第三章 入门岛L0(Git) 第四章 基础岛L1(书生全链路开源介绍) 第五章 基础岛L1(Demo&#x…

【计算机三级-数据库技术】操作题大题(第六套)

第六套操作题 第46题 假定要建立一个学校科研项目管理的信息系统,需要管理如下信息: 教师:教师编号、教师姓名; 项目:项目编号、项目名称、资助额: 学生:学生编号、学生姓名、学位&#xff0c…

Spring底层机制环境搭建

文章目录 1.模块创建和依赖引入1.聚合模块,下面有一个myspring2.查看父模块是否管理了子模块3.myspring模块引入基本包 2.进行环境搭建1.目录概览2.UserController.java3.UserService.java4.UserDao.java5.AppMain.java6.beans.xml7.测试8.配置UserController.java为…

教程3_单元层次结构1

单元层次结构是指通过将多个单元嵌套使用,形成具有层次结构的设计。每个单元可以包含其他单元的实例,这些实例称为“子单元”,而包含这些子单元的单元称为“父单元”。这种结构使得复杂设计变得模块化和可复用。 1、创建并使用单元实例 创建…

解读电子看板如何助力线缆行业目视化改革

线缆行业作为国民经济的重要组成部分,其生产过程复杂,环节众多,对生产效率和质量控制有着严格的要求。传统的管理方式往往难以满足现代化生产的需求,而电子看板的引入,为线缆行业带来了全新的管理理念和模式&#xff0…

23.合并K个升序链表-----力扣

一、题目: 给你一个链表数组,每个链表都已经按升序排列。 请你将所有链表合并到一个升序链表中,返回合并后的链表。 题目链接 二、示例: 输入:lists [[1,4,5],[1,3,4],[2,6]] 输出:[1,1,2,3,4,4,5,6] 解释…

​元宇宙虚拟展厅如何搭建?制作​线上虚拟展厅的成本

电子商务热潮的日益普及,让更多企业开始寻找具有创新性的方式来向客户展示他们的产品和服务。而元宇宙中的虚拟展厅也为企业提供了一个独特的机会,作为帮助企业展示其产品和服务特色的平台,元宇宙越发地受欢迎。不过在元宇宙中制作虚拟展厅的…

自带灭火电池?深蓝SL03托底事故揭秘

近日,网络上的一段热传视频,让不少网友看得先是惊心动魄,然后却又啧啧称奇。 该视频显示,8月18日晚上19点28分,一辆深蓝SL03在行驶中意外遭遇严重托底事故,车辆瞬间腾空跳跃,紧接着底盘出现明火…

【状态模式】设计模式系列:理解与实践(详细解读)

文章目录 状态模式详解:理解与实践1. 引言2. 状态模式简介2.1 定义2.2 应用场景2.3 与其他模式的关系 3. 状态模式的基本概念3.1 上下文(Context)类的角色3.2 状态(State)接口/抽象类3.3 具体状态(Concrete State)类3.4 UML类图和时序图 4. 状态模式的工作原理4.1 如…

用Python解决预测问题_多元线性回归模板

多元线性回归是一种统计学方法,用于分析两个或多个自变量(解释变量)与一个因变量(响应变量)之间的关系。在最简单的线性回归模型中,只有一个自变量和一个因变量,它们之间的关系可以用一条直线来…

Java对象的内存结构

文章目录 概述1. 对象头 (Header)Mark Word1. 32位HotSpot虚拟机中的MarkWord2. 64位HotSpot虚拟机中的MarkWord Class PointerArray Length指针压缩原理指针压缩测试 2. 实例数据 (Instance Data)3. 填充数据 (Padding Data) 查看 Java 对象的内存结构使用反射和VisualVM、JCo…

linux下的oracle启动命令

一、服务器断电后,手工启动oracle数据库步骤如下: 1、进入数据库服务器,切换到oracle用户,命令:su - oracle 2、启动数据库,命令: 1) sqlplus / as sysdba 2) startup 3)如果数据库已…

Rabbit mq 虚拟机stop无法重启

之前从后台进去&#xff0c;这个地方死活无法重启 然后重启docker 以及mq都不行 docker exec -it <CONTAINER_ID_OR_NAME> /bin/bash rabbitmqctl stop_app rabbitmqctl start_app 最后删除虚拟机&#xff0c;然后重建就行了 rabbitmqctl delete_vhost / rabbitmqctl…

C++ | Leetcode C++题解之第365题水壶问题

题目&#xff1a; 题解&#xff1a; class Solution { public:bool canMeasureWater(int x, int y, int z) {if (x y < z) {return false;}if (x 0 || y 0) {return z 0 || x y z;}return z % gcd(x, y) 0;} };

iPhone设备使用技巧:忘记密码的情况下如何解除iOS 18/17屏幕时间

我们给了儿子一部新手机。在尝试擦除旧手机上的所有内容并恢复出厂设置时&#xff0c;它要求提供 4 位屏幕时间密码。我已经尝试了我们会使用的所有可能性&#xff0c;但无法弄清楚。我们如何绕过这个问题或将手机恢复出厂设置以便我们可以出售它&#xff1f; Apple 社区 对于…

小琳AI课堂:Langchain

大家好&#xff0c;这里是小琳AI课堂&#xff0c;今天我们要探索一个令人兴奋的AI新概念——Langchain。 想象一下&#xff0c;如果我们可以把强大的大型语言模型&#xff0c;比如GPT-3&#xff0c;像乐高积木一样组合起来&#xff0c;会怎么样&#xff1f;这就是Langchain的核…

自定义开屏启动广告页

自定义开屏启动广告页 文章目录 自定义开屏启动广告页效果图简单版轮播方式css 效果图 简单版 图片 倒计时 <template><view class"guide fcc" :style"{ background: url(${ imgUrl }) no-repeat}"><view class"skip_btn" cli…

矢泽妮可二次元html视频动态引导页源码

源码介绍 矢泽妮可二次元html视频动态引导页源码 源码由HTMLCSSJS组成&#xff0c;记事本打开源码文件可以进行内容文字之类的修改&#xff0c;双击html文件可以本地运行效果&#xff0c;也可以上传到服务器里面&#xff0c;重定向这个界面 效果预览 源码下载 矢泽妮可二次…