模块导入和包

模块

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
my_moudle模块

模块的引用:针对同一模块的多次使用,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 '''
demo.py

我们可以从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的方式,超过三层一般就会不适用,模块里文件的相互调用一般在两层以内

 

posted @ 2017-08-09 16:07 前方、有光 阅读(...) 评论(...) 编辑 收藏