Python中两种引入模块的方式 - 纠正

横线下面的内容不用看了(当然,若想看也支持~),这里一句话道清模块引入的代码底层逻辑

一句化概括模块的引入

模块被导入后,底层是执行了一次模块代码,然后生成了一个相应的对象,叫模块对象,存在当前Python解释器会话中的sys.modules字典里,之后若再执行该模块的引入(通过任一种引入方式)都是调用sys.modules字典中存储的该模块生成的模块对象,再引入方的命名空间中

将对象

或对象的属性

的引用

给到同名变量上~~~

————————————————————————————————————————

Python中引入模块有些书上讲不清楚,你们是否见过"覆盖",等词语,让我们来纠正一哈~

会先讲使用方式和原理以便之后结论的证明,急查可以直接跳到总结

咱知道,Python中,引入模块的方式有两种

第一个是import 模块名

第二个是from 模块名 import 模块中属性

在一个.py文件中,

在运行该.py文件的过程中,

模块中的代码也会被执行,然后Python会将其添加到

sys.modules(专门用来装模块对象的字典),范围是在整个程序

同一个模块,运行过程中只会执行一次,

如果两次引入一个模块,第二次只是将之前存在

模块对象字典 sys.modules 中的 相应 属性(广义,包括模块对象,和一些模块中零散(from)引入的属性)

再次赋值给 本文件中 命名空间中的 同名变量上

我们需认清:

在Python中,任何东西都是对象,

而变量可改变的实际上是引用,即变量的指向,而不是其所指向对象的值

import 进来的模块,是一个整体,执行后生成一个模块对象,(有什么不懂的结尾或许能给你解惑)

添加给sys.modules,

然后,将这个模块对象的引用

赋值给本文件的 命名空间中的与模块同名的变量上

from 进来的模块,实际上引入的是模块中的属性,添加到sys.modules中

然后赋值给本文件的 命名空间中与属性同名的变量上

区别就在于

装对象的变量,我们一般访问的是其中的属性,因为使用的是 变量名.属性 的方式,并不会修改变量的指向

装属性的变量,我们修改的就是变量的指向,因为是直接 变量名 = 值 的方式,

这个值如果是int型的,就是将一个int型的对象的引用赋给了变量。

咱们再次引入时,

如果使用import,则是将sys.modules中的模块对象的引用再次赋值给到本文件的 命名空间中与模块同名的变量

而from import,则是将sys.modules中的属性再次赋给了本 文件的 命名空间中与属性同名的变量。

即:再次使用 同一引用语句 的作用只是

将 sys.modules中的对应的属性 再次赋给 本文件命名空间中 同名变量,而不是"刷新"了sys.modules中的相应属性(广义)

即需要认清,我们使用时使用的是变量,变量只能更换指向,如果变量指向的是对象,则可以通过变量改变 其所指向对象中 属性的值。

另外,有人可能认为,会改变所引用模块本体,这个是不会的,引入后,只是在本文件中创建了,同一个Python解释器会话中sys.modules字典是所有文件共用的,也就是说,其中的模块对象也是各页面文件共用的(当然,要引入才能用),因此各文件对模块对象的修改会改变这一会话中的模块对象。一句话说:引入同一个模块对象的文件操作的都是同一个模块对象。

细节:

执行一个Python程序时,通常从一个主脚本(通常时一个.py文件)开始执行。

导入某个模块的代码一旦被执行,首先会检查sys.modules是否已有该模块对象,若无

Python就会执行该模块的代码,创建该模块的全局命名空间

并将 模块对象存储 在 会话级别的(可以理解成整个程序执行过程中的) sys.modules字典中。

当同一个Python解释器会话中再次尝试导入同一个模块,Python会consys.modules检索以存入这个模块的对象,并将其引用赋予给引用方命名空间中的同名变量。

之后的每次引入都是如此,将sys.modules中的相应模块对象的引用给到引用房的同名变量。

由此也可见,在一个Python解释器会话中,一个模块通过引入语句引入后,就会执行并生成一个模块对象,添加到sys.modules中,之后,每次执行对该模块的引入语句,都是将sys.modules中的相应模块对象的引用给到引用方命名空间的同名变量。也就是说,这个Python解释器会话中,所有.py文件引入到模块对象其实是共用的,一个文件中对某个模块对象进行了修改,会影响其他引入了此模块对象的.py文件,一句话说:引入同一个模块对象的文件操作的都是同一个模块对象。

再了解一下命名空间,一个Python程序中一个.py文件就是一个模块,模块中的代码属于该模块的全局命名空间,所以各模块中有相同的变量名才不会有影响。

命名空间分为,当前模块的全局命名空间(Global),python的内置命名空间(Built-in),嵌套命名空间(Enclosing),和局部命名空间(Local)

总结

模块代码最多执行一次,执行后产生模块对象,放到sys.modules中,每当有文件执行引入该模块的语句,sys.modules中的模块对象就给到文件中同名变量,对变量的修改不会影响对象,除非修改对象本身或修改对象的属性。

也就是说,关于本次主要讨论的问题,结论是:

没有 "引入后值以初始值覆盖已有值" 一说,而是再一次将sys.modules中的模块对象给到文件中的同名变量。

两种模块导入方式不管先执行哪一种,模块代码都只执行一次,这叫"模块的单次导入性"。

生成的都是一个模块对象,添加到当前Python解释器的会话中的sys.modules里,

之后其它文件若进行引入就是使用sys.modules中已有的该模块对象进行映射

其中

【import 模块名】 是把模块对象以引入方中的变量名进行映射,通过变量名来访问其中属性,每次执行 import 都会将模块对象再次映射到同名变量,由于是对象,则以对象名.属性名(通过同名变量.属性名)的方式进行访问。

【from 模块名 import 模块中指定的名称】 是把模块对象中指定的属性名以引入方中的变量名进行映射,每次执行from import都会将模块对象中的相应属性再次映射到同名变量,由于是属性直接映射,则直接以 属性名(通过同名变量) 访问

抽象而精辟地讲:

import是将模块对象整个引入(映射)是直接对模块对象操作,给模块对象.属性的赋值语句改的是属性,并不影响变量的指向(变量指向的是对象);而from import是将模块内部属性零散引入(映射),不会直接改变模块对象的属性,赋值语句改的是变量的指向(原指向模块对象的属性,赋值后指向新赋予的值(也是一个对象,Python中所有东西都是对象)),对象属性没被修改。

我们知道了import和from import的区别(映射方式不同)和共同点(每次执行语句都进行映射),知道了Python中整数、浮点数、字符串、列表、字典..都是对象,知道了命名空间的种类,知道了模块单词单次导入性(首次执行引入语句时,执行模块代码,生成模块对象,存在sys.modules中,之后引入直接调用sys.modules中的模块对象进行映射),知道了同一个Python解释器会话中所有文件(若有引入相同模块),则共同操作sys.modules字典中的模块对象。

不知道我用映射这个次准不准确嘞~

如有疑问,或改进的地方请私信或评论区告知,十分需要大家的指正,互相助力,加油~

另提一嘴,Python中所有东西都是对象,包括数值,一次赋值就改变变量的指向。

而Java中数值、boolean等是基本数据类型,不是对象,他们直接存储数值,赋值就是改变变量的值。

可以慢慢体会体会吧~~~~~~~

  • 10
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值