注:此为慕课网Python(不打广告)视频的观看笔记,只做记录之用,并未勘误。
Python项目的代码要求:
高性能,封装性(可复用)、抽象
自己写程序的要求:
不单追求简单业务逻辑。更要考虑封装性
项目结构:
顶级结构: 包 文件夹,类似jar,dll等
二级结构: 模块 .py文件,单文件可包含多个类,也可以不定义类,但最好用类组织起来
三级结构: 类
函数、变量(类的特性)
包和模块的命名:
与文件夹和文件的名称相同
区分不同包的模块:使用命名空间
baoA.module
baoB.module
注意:
包可以包含字包
如果想让文件夹成为一个包,那么必须含有一个_init_.py文件
__init__.py叫做init模块,如果需要引用,形式
不是bao.__init__而是bao,用包的名称即 import bao 即可引入他
包的相互引入:
引入的第一种方式
如果 import 包名,那么会引入执行该包的全部代码
对于包内模块的引入:
模块AB同级:
如果A模块引用B模块定义的变量param
那么需要在A模块内 import module_name
即:在A模块内:import B; print(B.param),有严格的先后顺序
模块AB不同级:
加上包的命名空间即可:
import bao.B; print(bao.B.param),
精简:import bao.B as m; print(m.param),//缩短点引用
注意:
在python中一旦发生模块之间的import引用,就会在包下面生成pycache文件夹
__pycacahe__文件夹和期内的.pyc文件是自动生成的,与py虚拟机相关
在VSCODE中的配置页内的"files.exculed"中添加"__pycache__":true,则会隐藏文件
引入的第二种方式
使用from..import..
特点:可以引用单变量,也可以同import:form bao import B; print(bao.B.param)
例如 from bao.B import param ; print(param)
全部引入:
from bao.B import * ; 可以把B内变量全部引入,但是会混淆当前模块定义
控制需要引入的变量:仅适用本方式
例如在B模块中有三个变量,但只需import变量param,那么需要在
B模块中第一行:添加模块内置属性 __all__ = ['param']
此时使用 from bao.B import *; 时只能导入param变量
规范的引入:
首先明确,python内一行代码字符不超过80个
from bao.B import a,b,c,d,e,f 如果需要换行,那么可以加反斜杠换行:
from bao.B import a,b,c,\
d,e,f
或者使用括号,保证其连接性(适用场景很多):
from bao.B import (a,b,c,
d,e,f)
init.py的作用:
其相当于在全部代码前夹上init内的代码,引用包bao内的模块B时,会自动执行该包内的init模块
例如:
引用包bao内的模块B时,自动执行bao内的init模块
__init__的功能:
在init内,通过 __all__ = ['B']来控制此包内能够被引用的模块
在init内,添加公共 import 的类库,
例如在包common内的init模块中添加公共库之后,在其他代码中只需 import common即可批量添加类库
引入的注意事项:
包和模块不会重复导入,类似static代码块,只导入一次
避免循环导入
例如在模块A内 import B,在模块B内 import A 会陷入循环引入,要避免!
多模块间复杂引用时要避免因引用过多产生环链
关注 import 引入的内容
一旦导入的是一个模块,则就会执行模块的全部代码
无论在代码中重复引入多少次,引入的模块都只会执行一次
搞清入口文件:运行test.py时,其实就是将其作为入口文件
模块的内置变量
dir()函数:返回当前模块内的全部变量
内置变量:
__builtins__
__cached__
__doc__
__file__
__loader__
__name__
__package__
__spec__
用户自定义变量:
userA...
注意:
内置变量跟变量完全一样,内容可以被修改
<< 更多精彩尽在『程序萌部落』>>
<< https://www.cxmoe.com >>
使用打印输出变量信息:
print('name:'+__name__)
print('pakage:'+__package__)
print('doc:'+__doc__)
print('file:'+__file__)
错误信息排查:
Traceback (most recent call last):
File "h:/mooc/test/a1.py", line 1, in <module>
import test1.a1
File "h:\mooc\test\test1\a1.py", line 3, in <module
>
print('doc:'+__doc__)
TypeError: Can't convert 'NoneType' object to str implicitly
解释:
上述Traceback表示错误栈信息,会列出整个执行路径的全部出错信息,最后的Error是错误类型
应该先看最后的错误类型,然后通过错误栈来定位错误。
内置变量打印结果:
name:test1.a 模块的完整名称,带命名空间
pakage:test1 模块所属的包名
doc: 注释文件的注释信息
我是开头的注释
file:h:\mooc\test\test1\a.py 当前模块的物理路径
对于打印未知字符串,可以使用容错处理
print("可能的NoneType类型:" + param ) 修改为:
print("可能的NoneType类型:" + (param or '空值'))
(区别与上面的普通模块输出)
如果一个py文件被当做入口文件:那么此文件的
__name__ = '__main__',其会被强制改变,不在为文件名
__package__ = 'NoneType'即,入口文件不属于任何包
__file__ = '执行时的路径',即使用python 1/2/3.py时,此变量为1/2/3.py值不确定
另外:
import sys
print(dir(sys)) 打印系统内置变量,比模块的内置变量更多
内置变量 name 的作用
判断当前模块是否是被作为入口文件:
if __name__ == '__main__':
print('是入口文件,单独执行')
else:
print('作为模块被调用')
上述代码在a.py中,分别用a1调用和单独执行a:注意路径区别
a.py 在包test/test1下
a1.py 在包test下,代码是 import test1.a
H:\mooc\test\test1>python a.py
或 H:\mooc\test>python test1\a.py
是入口文件,单独执行
name:__main__
pakage:没有上一层的包 //注意
doc:
我是开头的注释
file:h:/mooc/test/test1/a.py
H:\mooc\test>python a1.py
作为模块被调用
name:test1.a //注意
pakage:test1
doc:
我是开头的注释
file:h:\mooc\test\test1\a.py
将可执行的文件当做模块来调用:
H:\mooc\test>python -m test1.a
是入口文件,单独执行
name:__main__
pakage:test1 //注意
doc:
我是开头的注释
file:H:\mooc\test\test1\a.py
注意上述三中运行方式的区别!!!!
包和模块导入时的绝对和相对路径
顶级包,与入口文件的位置有关
顶级包是相对于入口文件以外的文件来说的,
对于一个项目,在入口文件中需要import 包路径.模块名
而包路径就关乎顶级包的正确确定
绝对引入:import 包路径.模块名
其中的包路径必须从顶级包开始
相对引入:使用
from .module 表示引入同级的模块
from ..module 表示引入上一层的模块
注意:
import 方式不能使用 . 方式
可以使用 from .module import x 的方式
但是,入口文件不能使用 .module 相对引入
另外,如果待引用模块位于入口文件的同一层。那么无法点引入,会报错
错误:尝试引用一个超过顶级包的模块
相对引入的机制:
使用内置变量__name__来找到模块,
因此,入口文件的name是‘_main_’,
所以如果想在‘入口文件这一层引入模块’,那么只能绝对引入
如果在‘入口文件的上一层’,并使用 python -m module 仍然可以使用相对引入,
因为这种方式,文件仍然是入口文件,但是__name__不会改变,故能够使用相对引入
😒 留下您对该文章的评价 😄