模块、包、目录规范与模块编写规范
作者:互联网
模块、包、目录规范与模块编写规范
一、什么是模块?
模块分三大类
1、内置模块,python自带的
2、第三方模块,别人写的,发布到网上的,pip导入的那种
3、自定义的模块,自己写的一个py文件就是一个模块,,m.py文件,这个m就是一个模块
自己写的一个文件夹,也是这一个模块
文件名:foo.py 模块名foo
模块的4种形式:
1、使用python写的.py文件
2、已经被编译为共享库或者dll的c或者c++扩展
3、把一系列模块组织到一起的文件夹(注:文件夹下一定有一个__init__文件),读这个文件夹就是读这个文件
就是包,,pickage
4、使用c编写并链接到python解释器的内置模块
二、为什么要用模块?
1、内置与第三方模块可以拿来就用,不用再造轮子,可以极大的提升效率。
2、自定义的模块:可以将程序的各部分功能提取出来,放到一个模块中,供大家共享使用。
好处是减少了代码冗余,使程序组织结构更加清晰。
三、如何用?
1、import foo # 这里的run是foo.py的名字,是run
实际上就是导入这个foo.py文件
2、首次导入模块会发生三件事:
1、执行foo这个文件
2、运行foo.py这个文件,将这个文件产生的所有变量名字都丢到叫foo的名称空间。
3、在当前文件中产生一个名字叫foo,该名字的内存地址指向2中叫foo的名称空间。
3、 首次导入会发生这三件事,再次导入时,都是引用第一次导入的内容。不会重复执行代码。
4、引用:
强调1:指名道姓的问某一个模块要名字对应的值
如:import foo
foo.f1.() # 执行foo.py中的f1()
强调2:无论是查看还是引用,都是以原模块为准,与调用位置无关
也就是调用的都是原模块的设置与变量值。
5、导入模块格式
如下:
import time
import random
import os
不要这样import time, datetime, random, os, sys,,乱
6、导入模块规范
导入顺序:
1、python内置模块
2、第三方模块
3、程序员自定义模块
7、import。。。 as ... 可以为导入的模块起个别名
如:
import foo as f
调用: f.f1()
8、 函数是第一类对象,即函数可以当成变量去用,可被赋值,可当参数,可当成返回值,可当容器的元素
模块也是第一类对象
9、模块的命名
纯小写,与变量名的命名规则一致
10、导模块可以在开始位置导入,可以函数内部导入。
二、 一个python文件有几种用途? 执行py文件 与导入py文件有什么区别?
一个py文件有两种用途
1、被当作程序运行
2、被当作模块导入
二者的区别?
被当作程序运行的时候,运行完后,内存即回收
被当作模块导入时,只有在引用者关闭、del的时候,内存才被回收
每个py文件都内置了一个属性变量叫'__name__'。
当foo被运行时,'__name__'的值为'__main__'
当foo被当做模块导入时,'__name__'的值为”foo“
三、from...import ...
与import 有什么区别?
1、import导入模块,使用这个模块的功能时,必须加import前缀
random.randint()
优点:肯定不会与当前名称空间中的名字冲突
缺点:加了前缀,显得很麻烦
2、from...import...执行的时候,也发生三件事
运行foo
产生一个名称空间,放入产生的变量
在当前名称空间拿到一个名字,该名字指向导入模块名称空间中的某一地址。
--当一个函数内定义global变量,例如函数前x=1 ,函数中global定义x=2
那么在这个函数没被调用时,x是1。
这个函数被调用后,再调用x就变成了2
from。。。import。。。导入,使用时,不用再加前缀
优点:代码更精简
缺点:容易混淆
3、不推荐 from foo import x, f1, get, change
4、不推荐 from foo import * 非常容易混淆 变量与函数
5、了解: __all__
每个py文件或者模块都有一个内置变量叫__all__,是一个列表,里面记录了本模块或者本文件所有的字符串名字。
from foo import *,,,,这个导入*,也就是导入全部__all__里面的所有名字
控制*代表的名字有哪些
6、起别名
import time as t
from foo import change as c
四、循环导入问题
编写程序,如果两个模块之间交叉互相引用,这是一种非常垃圾的设计,极易瘫痪。
如果实在是有需要,可以利用导入时不执行代码的特点,把交叉引用的东西,放到一个函数内部。
如: def f2():
from foo import f1
。。。
这种解决方案叫做”屎上雕花“
五、搜索模块的路径与优先级
无论是import 还是from ..import ,在导入模块时都涉及到查找问题
优先级:
1、内存(内置模块)
2、按照sys.path中存放的文件的顺序依次查找要导入的模块
import sys
执行print(sys.path)
sys.path的值是一个列表,存放了一系列的文件夹
其中,第一个文件列是当前执行文件所在的文件夹
了解:sys.modules可以查看当前已经加载到内存中的模块
print(sys.modules)可以查看当前加载的模块
了解:
import foo
del foo
此时查看内存中的sys.modules,可以看到foo路径还在内存中,这是python的内存优化机制
为什么没有删除,因为模块是全局的,很可能还会继续使用,或者其他地方还会调用,如果再调用的时候,直接从内存中调用会更加快捷。
首次导入,一定会是从硬盘找。
如果当前文件夹没有,内存也没有,怎么办?
先执行sys.modules.append(r'要导入模块的绝对路径')
然后再执行import 模块名称
六、区别py文件的两种用途
被当作程序运行的时候,运行完后,内存即回收
被当作模块导入时,只有在引用者关闭、del的时候,内存才被回收
被当作程序运行与被当作模块导入的区别。
每个py文件都内置了一个属性叫'__name__'。
当foo被运行时,'__name__'的值为'__main__'
当foo被当做模块导入时,'__name__'的值为”foo“
七、如何编写一个规范的模块
1、如果你的工作是要写一个模块的话,请在第1行加入注释说明,写明本模块的功能与描述
2、再导入其他模块 ,每个导入后面最好也加入描述
3、再定义全局变量,如果不是必须的,最好使用全局变量。后面加注释说明
全局变量的使用要慎重,可能会被别人把值修改掉。最好是都使用局部变量最好。独立性最好,不易被影响。
4、再定义类。 加注释文档说明
5、再定义函数。 函数内要跟上文档注释。
6、if __name__ == '__mail__':
开始主程序
八、包(有__init__的文件夹) 重要
1、什么是包?
包就是一个包含__init__.py文件的文件夹
2、为何要有包?
包的本质是模块的一种形式,包是用来被当做模块导入。
当导包(文件夹)的时候,有一个文件可以代替运行执行(运行包、创建名称空间、导入文件创建变量名称)。
包里面的所有文件功能,都被包含在__init__中。
可以将一个文件夹做成一个模块,导模块就是在导文件夹,就是在导__init__
包的作用就是为了导入,连同下面的文件。不是为了本身运行。
可以把多个文件夹,多个包,都组织到一个文件里面使用。
了解:python3,如果包里面没有__init__,不会出错。python2会出错。
被导入 和 被运行执行 ,是截然不同的两件事。
包可以规范有序的整理模块的功能,包可以把不同的功能放在不同文件分别管理,以升级、管理 、维护提供方便。
3、绝对导入与相对导入
绝对导入:
包的导入,强调三点:
1、站在模块设计者的角度,无论是import,还是from。。import,可以带.
如:from foo.m1 import f1
点的左边,必须是一个包,否则非法
可以带一连串的点,如:import 顶级包.子包.子模块
2、包A 和 包B 有同名模块,导入后也不会有冲突。
如A.a 和 B.a 来自两个名称空间
3、import导入文件时,产生名称空间中的名字来源于文件。
import包,产生的名称空间的名字同样来自于文件。即包下的__init__.py
相对导入: 仅限于包内,不能跨出包。
包内的导入,推荐使用相对导入。
包外的导入,推荐使用绝对导入。
import os
import sys
sys.path.append(os.path.dirname(os.path.dirname(__file__))
这条命令会取得当前文件夹的父级目录,并追加到sys.path中。
from core.src import run 然后即可从core包的src模块,导入run函数。
九、软件开发的目录规范
ATM---》 系统文件夹名称
bin 放启动文件
conf 配置文件,放帐号密码文件的 日志文件路径 等
db 数据库相关,对数据库读写操作 ,注册用户 读写表的数据,数据交互
lib 存放程序中常用的自定义模块
core 放最核心代码的逻辑 src.py
api 与外部数据的接口,接口主要用于业务逻辑提供数据操作。
log 存放日志文件
-----上面是包,下面是文件
run.py 程序启动文件,一般放在根目录。因为运行时会默认将运行文件所在的文件夹作为sys.path的第一个路径,这样就省去了处理环境变量的步骤。
setup.py 安装、部署、打包的脚本
requirements.txt 存放软件所需要依赖的外部python包的列表
readme 项目说明文件
代码文件规范
声明‘utf-8’
本模块说明注释
导入其他模块
定义全局变量---越少越好,越少越不容易出问题
定义类
定义函数
if __name__ == __main__
run()
-------------
import os
import sys
sys.path.append(os.path.dirname(os.path.dirname(__file__))
这条命令会取得当前文件夹的父级目录,并追加到sys.path中。
from core.src import run 然后即可从core包的src模块,导入run函数。
十、补充函数的知识点
类型提示:type hniting
def register(name: str, age: int, hobbies: tuple):
print(name)
print(age)
print(hobbies)
return ...
python定义函数的时候,变量参数是可以传入任何类型的。想传整数而实际传入字母,浪费时间,有个提示的话,更有效率。
C java 把程序员当驴, python把程序员当人,是会犯错误的
def register(name: str, age: "这里要写数字憨批", hobbies: tuple):
print(name)
print(age)
print(hobbies)
return ...
print(register.__annotations__) # {'name': <class 'str'>, 'age': '这里要写数字憨批', 'hobbies': <class 'tuple'>}
'''
标签:__,文件,规范,导入,模块,import,编写,foo 来源: https://www.cnblogs.com/leeyong49/p/16688808.html