分享

Python导入模块的深入探讨,零基础的千万别错过!

 静幻堂 2018-10-11
编程梦工厂 2018-10-10 13:43:08


模块的导入:私信小编007即可自动获取Python视频教程以及PDF!

  • 首先要知道导入模块有两种方式,一种是使用import + 模块名的方式导入,另一种是使用from+模块名+import+对象名的方式导入。


然后我们讨论下这期间的导入过程:

第一步:执行导入语句时,Python会创建一个空的模块对象,从上到下、逐一执行该模块内的语句,并且把在模块内部全局作用域(相对于模块自身来讲)定义的对象都作为模块对象的属性。

第二步:此时分两种情况:

  1. 第一种,如果使用的是"import module_name"的方式,此时Python会在全局作用域(当前程序中)定义名字为module_name的变量名,并且让变量名module_name指向模块对象,其实等同于赋值操作,即:将模块对象赋值给变量module_name;
  2. 比如执行import re 这条语句后,在当前文件中变量"re"就会指向re模块对象,举个例子:
#我们先来定义一个变量re
re = 521
print('导入re前的变量re为:',re)#打印re时输出数字521
#然后导入re模块
import re
#此时再次打印re
print('导入re后的变量re为:',re)
#导入后变量re不再指向521,而是指向模块对象。
#导入模块后,我们就可以使用模块对象的属性和方法,比如re.match(),这也符合对象属性语法。
输出:
导入re前的变量re为: 521
导入re后的变量re为: <module 're' from '/home/kk/anaconda3/lib/python3.6/re.py'>
  1. 第二种,如果使用的是from module_name import a,b,c的方式,此时Python不会定义模块对象的名字,而只是从模块对象的属性中把对象a,b,c取出来放到全局作用域中,可以理解为在全局作用域定义了变量名a,b,c 并且分别指向模块对象的属性中的a,b,c所指向的对象。
  2. 我们来做个实验,先创建一个py1.py文件,文件内容如下:
a = 123
b = [1,2,3]
print('导入成功')

然后我们用from方法导入模块:

from py1 import a,b
temp = [i for i in globals() if not i.startswith('_')]
print(temp)
输出:
导入成功
['In', 'Out', 'get_ipython', 'exit', 'quit', 'a', 'b']
#temp输出的是所有非下划线开头的全局变量

从输出结果上可以看出,当执行from语句后,Python执行了模块中每一条语句,所以输出了"导入成功" 四个字,并且全局变量中没有变量名py1。

然后我们在程序中加入 import py1 语句,并且初始化程序:

from py1 import a,b
temp = [i for i in globals() if not i.startswith('_')]
print(temp)
import py1
temp2 = [i for i in globals() if not i.startswith('_')]
print(temp2)
输出:
导入成功
['In', 'Out', 'get_ipython', 'exit', 'quit', 'a', 'b']
['In', 'Out', 'get_ipython', 'exit', 'quit', 'a', 'b', 'temp', 'py1']

从结果看出,只输出了一次“导入成功”,所以当执行import py1语句时Python并没有再次导入模块,因为导入模块的操作在执行from语句时已经完成,但是全局变量中多出来一个py1,所以import py1此时的作用只有一个:把模块对象赋值给py1,也就是说给模块对象命了个名字。(那个多出来的temp是因为第一次执行globals()时还没有定义temp,程序先执行等号右边的表达式)

然后我们再来看一个例子,来说明为什么说from 语句是从python对象的属性中取出变量的。

#首先我们用from导入模块,并取得变量a
from py1 import a
print('修改模块对象属性之前的a:',a)
#然后执行import py1,目的是给模块对象命名,以便操作它的属性
import py1
#给模块对象py1的属性a重新赋值
py1.a = 666
#然后再通过from语句重新取得a的值
from py1 import a
#我们来打印一下a 看看是多少
print('修改模块对象属性之后的a:',a)
输出:
导入成功
修改模块对象属性之前的a: 123
修改模块对象属性之后的a: 666

由此可以看出,from语句其实是从模块对象的属性中取处变量的,当模块对象中的属性改变时,取出来的变量也发生了改变。

最后,我们再来探讨一个问题:使用from导入模块后,当模块对象中的属性是可变对象时,在当前程序命名空间内修改该变量后,模块对象中该属性所指向的对象也会发生变化。可以理解为“共享可变对象”.

#还是用py1.py模块做实验,其中有两个变量:a=123 和b=[1,2,3]
from py1 import a,b
print('导入后a的值:',a)
print('导入后b的值:',b)
#a为不可变对象,但是我们可以把它重新赋值
a = 33
#b为可变的列表,我们对b进行修改
b[0] = 777
#然后我们打印一下a和b
print('修改后a的值:',a)
print('修改后b的值:',b)
#然后我们执行一下import py1,目的是让变量py1指向模块对象,然后打印对象py1中的属性a和b
import py1
print('模块对象py1的属性a:',py1.a)
print('模块对象py1的属性b:',py1.b)
#从结果可以看到,a是不可变类型,所以对a的重新赋值对模块对象中的a没有影响。
#但是因为b是可变对象,所以修改b后,模块对象中的b也改变了,因为它们指向的是同一个可变对象。
输出:
导入成功
导入后a的值: 123
导入后b的值: [1, 2, 3]
修改后a的值: 33
修改后b的值: [777, 2, 3]
模块对象py1的属性a: 123
模块对象py1的属性b: [777, 2, 3]


本文所述仅代表本人个人理解,如果对您有了些许帮助 那么恭喜您更进一步。

    本站是提供个人知识管理的网络存储空间,所有内容均由用户发布,不代表本站观点。请注意甄别内容中的联系方式、诱导购买等信息,谨防诈骗。如发现有害或侵权内容,请点击一键举报。
    转藏 分享 献花(0

    0条评论

    发表

    请遵守用户 评论公约

    类似文章 更多