模块
import
一个模块就是一个包含了Python定义和声明的文件,文件名就是模块名字加上.py的后缀
模块的使用:假如自定义一个模块my_moudle.py,文件名my_moudle.py,模块名my_moudle
1 #my_moudle.py 2 print('from the my_moudle.py') 3 4 money=1000 5 6 def read1(): 7 print('my_moudle->read1->money',money) 8 9 def read2(): 10 print('my_moudle->read2 calling read1') 11 read1() 12 13 def change(): 14 global money 15 money=0
模块的引用:针对同一模块的多次使用,Python为了防止多次重复导入,Python会增加一系列的优化:第一次导入后就将模块名加载到内存了,后续的import语句只是对加载到内存的模块的一次引用,不会重新执行模块内的语句
1 #demo.py 2 import my_moudle #只在第一次导入时才执行my_moudle.py内代码,此处的显式效果是只打印一次'from the my_moudle.py',当然其他的顶级代码也都被执行了,只不过没有显示效果. 3 import my_moudle 4 import my_moudle 5 import my_moudle 6 7 ''' 8 执行结果: 9 from the my_moudle.py 10 '''
我们可以从sys.module中找到当前已经加载的模块,sys.module是一个字典,内部包含模块名与模块对象的映射,该字典决定了导入模块时是否需要重新导入。
每个模块都是一个独立的名称空间,定义在这个模块中的函数,把这个模块的名称空间当做全局名称空间,这样我们在编写自己的模块时,就不用担心我们定义在自己模块中全局变量会在被导入时,与使用者的全局变量冲突
1 #测试一:money与my_moudle.money不冲突 2 #demo.py 3 import my_moudle 4 money=10 5 print(my_moudle.money) 6 7 ''' 8 执行结果: 9 from the my_moudle.py 10 ''' 11 测试一:money与my_moudle.money不冲突
首次导入模块会做一下三件事:
1.为源文件(my_moudle模块)创建新的名称空间,在my_moudle中定义的函数和方法若是使用到了global时访问的就是这个名称空间。 2.在新创建的命名空间中执行模块中包含的代码,见初始导入import my_moudle 3.创建名字my_moudle来引用该命名空间
为模块起别名:
1 import my_moudle as sm 2 print(sm.money)
为模块起别名,根据用户的输入选择不同的功能
#mysql.py def sqlparse(): print('from mysql sqlparse') #oracle.py def sqlparse(): print('from oracle sqlparse') #test.py db_type=input('>>: ') if db_type == 'mysql': import mysql as db elif db_type == 'oracle': import oracle as db db.sqlparse()
1 if file_format == 'xml': 2 import xmlreader as reader 3 elif file_format == 'csv': 4 import csvreader as reader 5 data=reader.read_date(filename)
from.(父模块名)..import..(子模块名)...
这样导入模块可以导入你需要的,对于不需要的不加载(个人见解,原创(#^.^#))
如果对于导入的模块有重名会发生覆盖效果
1 #demo.py 2 from my_moudle import read1 3 def read1(): 4 print('==========') 5 read1() 6 ''' 7 执行结果: 8 from the my_moudle.py 9 ========== 10 '''
Python中的变量赋值只是一种绑定关系,而不是存储操作(就好比a=7,是把a与,7暂时绑定,让a代替7干想干的事,而不是说a就是7,a只能存储7这个数据《原创(~ ̄▽ ̄)~》)
1 from my_moudle import money,read1 2 money=100 #将当前位置的名字money绑定到了100 3 print(money) #打印当前的名字 4 read1() #读取my_moudle.py中的名字money,仍然为1000 5 6 ''' 7 from the my_moudle.py 8 100 9 my_moudle->read1->money 1000 10 '''
和文件操作类似,也支持as
1 from my_moudle import read1 as read
支持导入多行
1 from my_moudle import (read1, 2 read2, 3 money)
from my_moudle import * 把my_moudle中所有的不是以下划线(_)开头的名字都导入到当前位置,大部分情况下我们的python程序不应该使用这种导入方式,因为*你不知道你导入什么名字,很有可能会覆盖掉你之前已经定义的名字。而且可读性极其的差,在交互式环境中导入时没有问题。
__all__=['money','read1'] #这样在另外一个文件中用from my_moudle import *就这能导入列表中规定的两个名字
*如果my_moudle.py中的名字前加_,即_money,则from my_moudle import *,则_money不能被导入
把模块当做脚本执行
即Python文件可以在cmd命令提示符下边当做脚本, __name__在谁的工作目录下调用返回的是谁的结果 (假如我自己调用自己的模块返回的是我自己的模块名,其他人调用返回的是他自己的) 魔铠的查找顺序:内存中加载的,内置模块,sys.path路径中包含的模块 查找模块内的所有子模块名(dir(模块名))
包(存在于一个文件夹中的模块的集合)
1 执行文件为test.py,内容 2 #test.py 3 import aaa 4 同级目录下创建目录aaa,然后自建空__init__.py(或者干脆建包) 5 需求:验证导入包就是在导入包下的__init__.py 6 先执行看结果 7 再在__init__.py添加打印信息后,重新执行 8 需求: 9 aaa.x 10 aaa.y 11 解决:在__init__.py中定义名字x和y 12 在aaa下建立m1.py和m2.py 13 #m1.py 14 def f1(): 15 print('from 1') 16 #m2.py 17 def f2(): 18 print('from 2') 19 需求: 20 aaa.m1 #进而aaa.m1.func1() 21 aaa.m2 #进而aaa.m2.func2() 22 23 解决:在__init__.py中定义名字m1和m2,先定义一个普通变量,再引出如何导入模块名 24 在aaa下新建包bbb 25 需求: 26 aaa.bbb 27 28 解决在aaa的__init__.py内导入名字bbb 29 在bbb下建立模块m3.py 30 #m3.py 31 def f3(): 32 print('from 3') 33 需求: 34 aaa.bbb.m3 #进而aaa.bbb.m3.f3() 35 36 解决:是bbb下的名字m3,因而要在bbb的__init__.py文件中导入名字m3 37 绝对导入变成相对导入 38 需求: 39 aaa.m1() 40 aaa.m2() 41 aaa.m3() 42 43 解决:在aaa的__init__.py中拿到名字m1、m2、m3 44 包内模块直接的相对导入,强调包的本质:包内的模块是用来被导入的,而不是被执行的 45 用户无法区分模块是文件还是一个包,我们定义包是为了方便开发者维护 46 将包整理当做一个模块,移动到别的目录下,操作sys.path
1. 无论是import形式还是from...import形式,凡是在导入语句中(而不是在使用时)遇到带点的,都要第一时间提高警觉:这是关于包才有的导入语法 2. 包是目录级的(文件夹级),文件夹是用来组成py文件(包的本质就是一个包含__init__.py文件的目录) 3. import导入文件时,产生名称空间中的名字来源于文件,import 包,产生的名称空间的名字同样来源于文件,即包下的__init__.py,导入包本质就是在导入该文件 强调: 1. 在python3中,即使包下没有__init__.py文件,import 包仍然不会报错,而在python2中,包下一定要有该文件,否则import 包报错 2. 创建包的目的不是为了运行,而是被导入使用,记住,包只是模块的一种形式而已,包即模块
两个包A和B,假如AB里边都有a模块,他们也不会冲突(处于两个命名空间)
绝对到导入和相对导入:
绝对导入:以该包的根目录作为起始
相对导入:用.或者..的方式作为起始(只能在一个包内使用)(可以在包的同级文件下测试)
特别需要注意的是:可以用import导入内置或者第三方模块(已经在sys.path中),但是要绝对避免使用import来导入自定义包的子模块(没有在sys.path中),应该使用from... import ...的绝对或者相对导入,且包的相对导入只能用from的形式。
单独导入包名称是不会导入包中的所有子模块
模块与包之间的调用:
在同一工作目录下用一个文件里调用另一个包里的内容可以采用import的方式,超过三层一般就会不适用,模块里文件的相互调用一般在两层以内