模块
1. 什么是模块?
常见的场景:一个模块就是一个包含了python定义和声明的文件,文件名就是模块名字加上.py的后缀。
1.1 模块的四个通用类别
- 使用python编写的代码(.py文件)
- 已被编译为共享库或DLL的c或c++扩展
- 包好一组模块的包
- 使用c编写并连接到python解释器的内置模块
2. 为什么要使用模块?
退出python解释器后重新进入,之前定义的函数或变量都将丢失,为了将其保存下来,需要时通过python test.py方式执行,此时test.py被称为脚本script.
随着程序的发展,功能越来越多,为了方便管理,我们通常将程序分成一个个文件,这样做程序的结构更清晰,方便管理。这是我们不仅仅可以把这些文件当做脚本去执行,还可以把他们当做模块来导入到其他的模块中,实现了功能的重复利用。
3. 怎么使用模块?
3.1 import
import 模块名
模块在一个程序中只会被导入一次,不会被重复导入。
import 模块名.函数名
单一调用某模块的函数使用,本地不能出现同名函数,如必须存在,则考虑给调用函数起别名。
如何实现的?
导入一个模块之后,会将模块存储在内存中,当再次导入的时候,就到内存中去查看是否导入过,如果导入过了就不再导入。
查看方法:
import sys
for i in sys.modules:
print(i)
3.2 别名
import re as ret
导入的模块都有自己的命名空间
当你给一个模块起了别名的时候,就产生了一个新的命名空间,这个命名空间只和别名相关。
应用场景
- 有两种sql模块mysql和orcale,根据用户的输入,选择不同的sql功能
#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()
- 为已经导入的模块起别名的方式对编写可扩展的代码很有用,假设有两个模块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.reader.read_date(filename)
3.3 导入多个模块
- 一行导入多个模块(python官网不建议这样书写)
import sys,os,re
- 多行导入多个模块
import sys
import os
import re
3.4 from … import …
这种形式是导入啥就能用啥,不导入的不能用
这个被import的名字就属于全局
支持别名
from my_module import read1 as read
支持导入多行
from my_module import (read1,
read2,
money)
支持*操作
from my_module import * 把my_module中所有不是以下划线(_)开头的名字或__all__列表里的名称都导入到当前位置,不建议这么做,因为*不知道你导入的什么名字,有可能覆盖掉你之前已经定义的名字。而且代码可读性差。
3.5 把模块当做脚本执行
我们可以通过模块的全局变量__name__来查看模块名:
当做脚本运行:
name__等于'__main'
当做模块导入:
name = 模块名
作用:用来控制.py文件在不同的应用场景下执行不同的逻辑
if name = "main"
def fin(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))
3.6模块搜索路径
模块的查找顺序:内存中已经加载的模块->内置模块->sys.path路径中包含的模块
需要特别注意的是:自己定义的模块名不应该与系统内置模块重名
import sys
print(sys.path)
注意:搜索时按照从左到右的顺序查找,位于前的优先被查找所以自我定义最好别与第三方模块重名,sys.path还可能包含.zip归档文件和.egg文件,python还是会把其当成目录去处理。
4.1 包
包是一种通过使用'.模块名'来组织python模块名称空间的方式。
- 无论是import形式还是from…import…形式,凡是在导入语句中(而不是在使用时)遇到带点的,都要第一时间提高警惕,这是关于包才有的导入语法
- 包是目录级的(文件夹级),文件夹是用来组成py文件(包的本质就是一个包含__init__.py文件的目录)
import导入文件时,产生名称空间中的名字来源与文件,import包,产生的名称空间的名字同样来源于文件,即包下的__init__.py,导入包本质就是导入该文件
强调:在python3中,即使包下没有__init__.py文件,import包仍然不会报错,而在python2中,包下一定要有该文件,否则import包报错
- 创建包的目的不是为了运行,而是被导入使用,记住,包只是模块的一种形式,包即模块
4.2创建包目录的代码
import os
os.makedirs('glance/api')
os.makedirs('glance/cmd')
os.makedirs('glance/db')
l = []
l.append(open('glance/__init__.py','w'))
l.append(open('glance/api/__init__.py','w'))
l.append(open('glance/api/policy.py','w'))
l.append(open('glance/api/versions.py','w'))
l.append(open('glance/cmd/__init__.py','w'))
l.append(open('glance/cmd/manage.py','w'))
l.append(open('glance/db/__init__.py','w'))
l.append(open('glance/db/models.py','w'))
map(lambda f:f.close() ,l)
4.3 init.py文件
不管是哪种方式,只要是第一次导入包或者是包的任何其他部分,都会依次执行包下的__init__.py文件,这个文件可以为空,也可以存放一些初始化包的代码。
4.4 绝对导入和相对导入
绝对导入
glance/
├── __init__.py from glance import api
from glance import cmd
from glance import db
├── api
│ ├── __init__.py from glance.api import policy
from glance.api import versions
│ ├── policy.py
│ └── versions.py
├── cmd from glance.cmd import manage
│ ├── __init__.py
│ └── manage.py
└── db from glance.db import models
├── __init__.py
└── models.py
绝对导入
相对导入
glance/
├── __init__.py from . import api #.表示当前目录
from . import cmd
from . import db
├── api
│ ├── __init__.py from . import policy
from . import versions
│ ├── policy.py
│ └── versions.py
├── cmd from . import manage
│ ├── __init__.py
│ └── manage.py from ..api import policy
#..表示上一级目录,想再manage中使用policy中的方法就需要回到上一级glance目录往下找api包,从api导入policy
└── db from . import models
├── __init__.py
└── models.py
相对导入
感谢
感谢eval美女倾囊相授
感谢为知笔记