python基础(模块和包)
一、 模块:
1.1 模块的定义:
定义:
模块的导入相当于执行了整个文件
一个模块不能被多次导入,一旦导入原文件中的修改也不会生效
一个模块被导入后,再次导入这个模块时,解释器会检测modules字典中对否在这个模块名,存在就不再执行这个模块
from导入时,当前文件中不要使用和导入的模块中的变量相同的名字,避免变量冲突
模块不建议循环导入,循环导入会可能会导致一些无法预料的错误
导入一个模块的时候命名空间的变化:
第一:创建了一块属于这个模块的命名空间
第二:创建了一个变量 指向这个命名空间
第三:执行这个文件
示例:
# 示例: import my_module # 自建模块 my_module a = 'alex' b = 'sb' my_module.a my_module.b my_module.read()
# my_module模块: print(123) a =1 b =1 def read(): print(a)
1.2 一次性导入多个模块与一个模块导出多个变量:
import time,os,random,my_module # 一次性导入多个模块,不建议这样导入 from my_module import a,b,read # 一个模块一次性导入多个模块变量名(变量 + 函数) from my_module import a as aa,b as bb,read as r # 多个变量名重新赋值
1.3 模块加载路径/手动加载绝对路径/查看系统模块字典:
import sys print(sys.modules) # 查看加载的系统模块字典,这里是所有当前加载的模块 print(sys.path) # 查看系统模块的加载路径 sys.path.append(r'D:\PyCharmProject\s20\day26\demo') # 手动添加系统模块的加载的绝对路径
1.4 模块导入之as语法:
格式:
import 模块名 as 变量名
from 模块名 import 模块中的变量名(变量 + 函数) as 变量名
定义:
as是把加载的模块命名空间地址赋值给as后面自定义的变量名
# 示例: import time as t # time失效 ,变量t指针指向time模块的命名空间 t.time() # 小实例: mode = 'pickle' if mode == 'pickle': import pickle as mode else: import json as mode # 写文件: def dump(mode, obj): with open('a', mode='w') as f: mode.dump(obj, f) # 读文件: def load(mode): with open('b', mode='r') as f: mode.load(f)
1.5 *语法和__all__ :
格式:
__all__ = ['字符串数据类型的变量的名']
定义:
通过__all__ = ['a', 'b', 'read']来约束(from 模块名 import *)这种模式,这里只会生效列表中的变量名
如果模块再次通过指定变量名重新导入,__all__ 不约束重新导入的指定变量
示例:
# 示例: from my_module import * # __all__ = ['字符串数据类型的变量的名'] from my_module import c # __all__ 不约束重新导入的指定变量 # 模块变量: print(a) # 2 print(b) # 1 # 模块方法: read() # 2 # 指定导入变量名 print(c) # 5
# my_module模块: __all__ = ['a', 'b', 'read'] print(123) a = 2 b = 1 c = 5 def read(): print(a)
二、 包:
2.1 定义:
加载这个包时,相当于执行了这个包中的init文件
包中存在一个或者多个模块文件
包中可能存在多个包文件,每个包文件中有一个init文件
2.2 __init__文件:
init文件里面常配置一些文件导入的初始化配置
只要是第一次导入包或者是包的任何其他部分,都会依次执行包下的__init__.py文,这个文件可以为空,但是也可以存放一些初始化包的代码
2.3 import导入方式:
根据包的导入要精确到模块名,不能精确到具体的函数或者变量
然后使用glance.api.policy或者重命名的方式使用这个模块中变量名
示例:
import glance.api.policy as policy # 路径(glance.api) 模块名(policy) policy.get() # 自定义模块名 + 变量名 执行这个函数
2.4 from import导入方式:
使用from import import后面至少是精确到模块的
示例:
# 方式一: from glance.api import policy # 包路径(glance.api) policy.get() # 模块调用 # 方式二: from glance.api.policy import get get()
2.5 绝对导入和相对导入:
例如:我们在glance/api/version.py中想要导入glance/cmd/manage.py
在glance/api/version.py #绝对导入 from glance.cmd import manage manage.main() #相对导入 from ..cmd import manage manage.main()
相对导入方式:
特点:
用.或者..的方式最为起始(只能在一个包中使用,不能用于不同目录内)
相对导入格式为 from .A import B 或 from ..X import Y,. 代表当前模块,.. 代表上层模块,... 代表上上层模块,依次类推
需要注意:存在相对导入语句的模块,是不能直接运行的。需要去包外部执行,否则会引发异常错误
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
绝对导入方式:
特点:
绝对导入的格式为 import A.B 或 from A import B
以glance作为起始(包的项目文件中的起始路径)路径
可以通过os.path.dirname(__file__)获取当前文件的父目录路径
可以通过sys.path.append(路径名),添加包的加载路径
# 示例: import os print(os.path.dirname(__file__)) # 获取当前文件的父目录路径 print(os.path.dirname(os.path.dirname(__file__))) # 获取父目录的路径的上层目录
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
2.6 补充:dir()函数
内建函数dir是用来查找模块中定义的名字,返回一个有序字符串列表
import time print(dir(time))
三、 软件设计规范:
3.1 项目示例:
项目: --bin # 项目的启动文件装在这个文件夹下 -- strat.py -- conf # config配置,配置文件 -- settings.py # 可能会发生改变的配置信息 -- core # 核心代码 实际的python代码实现功能所在的文件 -- user.py -- auth.py -- main.py -- lib # 一些需要使用到的库文件 -- db # 数据库(database) 一堆数据文件 -- log # 日志
包的相对导入与绝对导入可参考:https://www.cnblogs.com/gaowengang/p/8543840.html