1、看一个例子:
创建一个demo.py文件:
print('in demo.py')
def hello():
print('in hello function')
然后我们在另外一个文件中import这个demo文件:
import demo
# 调用demo.py文件中的hello()函数
demo.hello()
注意,demo后面没有py。
运行,产生结果:
模块:就是包含了Python定义和声明的文件,文件名就是模块名称加上.py的后缀。
import加载的模块分为4个通用类别:
1)使用python编写的代码(.py文件)
2)已被编译为共享库或DLL的C或C++扩展;
3)包好一组模块的包;
4)使用C编写并链接到python解释器的内置模块;
2、为什么使用模块?
我们退出python解释器,然后再重新进入,之前定义的函数或变量都将丢失,因此我们通常将程序写到文件中便可永久地保存下来,需要的时候就通过python test.py的方式去执行,此时test.py被称为脚本script。
随着程序的发展,功能越来越多,为了方便管理,我们通常将程序分为一个个的文件,这样程序的结构更清晰,方便管理。这样,我们不仅仅可以将这些文件当脚本去执行,还可以把他们当作模块来导入到其他的模块中,实现了功能的重复利用。
3、如何使用模块:
import语句。
1)模块可以包含执行的语句和函数的定义。它们只在模块名第一次遇到import语句的时候才被执行,import语句可以在程序中的任意位置使用,可针对同一个模块import多次,为了防止重复导入,python的优化手段是:第一次导入后就将模块名加载到内存了,后续的import语句仅是对已经加载到内存中的模块对象的一次引用,不会再重新执行模块中的语句。
import sys
print(sys.modules)
2)我们可以从sys.modules中找到当前已加载的模块,sys.module是一个字典,内部包含模块名和模块对象的映射, 改字典决定了导入模块时是否要重新导入。
3)名称空间:每个模块都有自己的名称空间,定义在这个模块中的函数,把这个模块的命名空间当作全局名称空间,这样,我们在编写自己的模块的时候,就不用担心我们定义在自己模块中的全局变量会在被导入时,与使用者全局变量冲突。
4、import文件做的完整流程:
1)先从sys.modules里查看是否已经被导入;
2)如果没有被导入,就依据sys.path路径取寻找路径;(导入包寻找路径)
3)找到了就导入;
2)创建模块的命名空间;
3)执行文件,把文件的名字都放到命名空间中;
5、为模块起别名:
import time as t
print(t.time())
别名的应用场景:
#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
为已经导入的模块起别名的方式对编写可扩展的代码很有用,假设有两个模块xmlreader.py和csvreader.py,它们都定义了函数read_data(filename):用来从文件中读取一些数据,但采用不同的输入格式。可以编写代码来选择性地挑选读取模块,例如
if file_format == 'xml':
import xmlreader as reader
elif file_format == 'csv':
import csvreader as reader
data=reader.read_date(filename)
提高了代码的兼容性。
注意的是:重命名之后,原来的module的名称就不能使用了,只能使用重命名的名称。
6、一行导入多个模块:
import time os re
我们在实际工作中,不建议这么使用。建议是分开写,以后注释也非常方便,代码也非常方便阅读。
在文件的开头部分,将所有的导入模块都列出来。
编码规则,导入模块也分先后顺序:
1)导入内置模块;
2)扩展的模块;例如:django模块
3)自定义的模块;
7、from...import...
1)import my_module, 会将源文件的名称空间my_module带到当前的名称空间中,使用时必须是my_module.名字的方式。
而frome语句相当于import, 也会创建新的命名空间,但是将my_module中的名字直接导入到当前的命名空间中,在当前的命名空间中,直接使用函数名字就可以了。
这两种方式各有千秋。
#测试一:导入的函数read1,执行时仍然回到my_module.py中寻找全局变量money
#demo.py
from my_module import read1
money=1000
read1()
'''
执行结果:
from the my_module.py
spam->read1->money 1000
'''
#测试二:导入的函数read2,执行时需要调用read1(),仍然回到my_module.py中找read1()
#demo.py
from my_module import read2
def read1():
print('==========')
read2()
'''
执行结果:
from the my_module.py
my_module->read2 calling read1
my_module->read1->money 1000
'''
2)如果有重名的read1和read2, 那么会有覆盖的效果。
我们使用from * import read1, 那在本地的命名空间中全局就能使用read1, 但是,如果我们在本地定义了一个read1函数,就不能在本地命名空间中使用到这个read1函数了,会有一个覆盖的效果。
3)from demo import money, 这是一个变量。
需要特别强调的一点:python中的变量赋值不是一种存储操作,而只是一种绑定关系。
4)from demo import * 这种方式不太安全,可能会覆盖掉你之前已定义的名字,可读性极差,在交互环境中导入是没有问题的。
# demo.py
print('in demo.py')
money = 100
def hello():
return 'in hello function', 100
# 01homework.py
__all__ = ['money'] # 这个地方做了限制,只能有money这个变量, 这个__all__只跟这个*有关联
from demo import *
print(money)
ret = read() # 在pycharm中,read有红色的波浪线显示read函数名无效
print(ret)
结果:
5)也支持重命名:
from demo import read as r
6)支持导入多行:
from demo import (read1,
read2,
money)
7)如果在demo.py文件中的变量名字前加_, 即_money, 则from demo import *, 则_money变量不能被导入。
8、把模块当着脚本执行:
我们可以通过模块的全局变量__name__来查看模块名:
当作脚本运行:
__name__ 等于'__main__'
当作模块导入:
__name__ = 模块名
作用:用来控制.py文件在不同的应用场景下执行不同的逻辑。
def fib(n):
a, b = 0, 1
while b < n:
print(b, end=' ')
a, b = b, a+b
print()
if __name__ == "__main__":
print(__name__)
num = input('num :')
fib(int(num))
再看一个例子:
# demo.py 文件
def login():
print('Doing login function!')
def hello():
print('in read1', money)
def hello2():
print('in read2')
money = 100
print('in demo.py')
# 如果直接执行的是当前的py文件,,那么__name__的值就等于__main__,
# 如果是在别的模块文件中导入引用该文件模块,那__name__的值就等于模块名,
# 那我们通过这种机制,就给程序两种状态。在别的模块执行,那下面的这段程序就不执行。
if __name__ == '__main__':
ret = login()
print(ret)
9、总结:
所有的模块导入,都应该尽量写在代码的开头部位。顺序:内置模块、拓展模块、自定义模块。
import 模块名:
模块名.变量名和本地的同名变量名不会发生冲突
import 模块名 as 重命名的模块名, 提高代码的兼容性,完成相同的功能,使用相同的名字,例子:数据库和文件
import 模块名1 模块名2 模块名3 不推荐这种写法
from 模块名 import 变量名:
直接使用变量名,就可以完成操作
如果本文件中有相同的变量名就发生冲突,这个要注意的。
from 模块名 import 变量名 as 重命名的变量名
from 模块名 import 变量名1 变量名2 变量名3
from 模块名 import * 将模块中的所有变量名都放到内存中。你都不知道模块中有哪些名字,容易导致冲突。
from 模块名 import * 和__all__是一对。没有这个变量,会导入所有的名字,如果有all,只导入,只导入all列表中的变量。