二.昨日内容作业讲解
- 装饰器:完美的呈现了开放封闭原则。装饰器的本质:闭包。
def wrapper(f): def inner(*args,**kwargs): """执行被装饰函数之前的操作""" ret = f(*args,**kwargs) """执行被装饰函数之后的操作""" return ret return inner
三.具体内容
1.自定义模块:
什么是模块:本质就是.py文件,封装语句的最小单位。
自定义模块:实际上就是定义.py,其中可以包含:变量定义,可执行语句,for循环,函数定义等等,他们统称模块的成员。
2.模块的运行方式:
-
脚本方式:直接用解释器执行。或者PyCharm中右键运行。
-
模块方式:被其他的模块导入。为导入它的模块提供资源(变量,函数定义,类定义等)。
3.__name__
属性的使用:
在脚本方式运行时,__name__
是固定的字符串:__main__
在以模块方式被导入时,__name__
就是本模块的名字。
在自定义模块中对__name__
进行判断,决定是否执行可执行语句:开发阶段,就执行,使用阶段就不执行。
""" 自定义模块 模块中出现的变量,for循环,if结构,函数定义。。。。称为模块的成员。 """ # 可执行语句 a = 1 # print(a) # for x in range(3): # print(x) # 函数定义 def f(): print('hello world') # f() # __name__:脚本方式运行时,固定的字符串:__main__ # 以导入方式运行时,就是本模块的名字 # print(__name__) # 定义一个函数,包含测试语句 def main(): print(a) for x in range(3): print(x) f() if __name__ == '__main__': main()
4.系统导入模块的路径
-
内存中:如果之前成功导入过某个模块,直接使用已经存在的模块
-
内置路径中:安装路径下:Lib
-
PYTHONPATH:import时寻找模块的路径。
-
sys.path:是一个路径的列表。
如果上面都找不到,就报错。
通过动态修改sys.path的方式将自定义模块添加到sys.path中。
os.path.dirname():获取某个路径的父路径。通常用于获取当前模块的相对路径
import sys import os sys.path.append(os.path.dirname(__file__) + '/aa')
""" 测试自定义模块的导入 """ # 自定义模块被其他模块导入时,其中的可执行语句会立即执行 # import a # import time # 使用自定义模块的成员 # print(a.a) # a.f() # python中提供一种可以判断自定义模块是属于开发阶段还是使用阶段。 # 查看sys.path内容,系统查找模块的路径。 # import sys # print(sys.path) # 使用os模块获取一个路径的父路径 # import os # print(os.path.dirname(__file__)+ '/aa') # 添加a.py所在的路径到sys.path中 # import sys # # sys.path.append(r'D:python_22day15aa') # 上述路径是写死的,不好。 # 应该使用相对路径。 # 使用相对位置找到aa文件夹 # print(__file__) # 当前文件的绝对路径 import sys import os sys.path.append(os.path.dirname(__file__) + '/aa')
5.导入模块的多种方式:
-
import xxx:导入一个模块的所有成员
-
import aaa,bbb:一次性导入多个模块的成员。不推荐这种写法,分开写。
-
from xxx import a:从某个模块中导入指定的成员。
-
from xxx import a,b,c:从某个模块中导入多个成员。
-
from xxx import *:从模块中导入所有成员。
""" 自定义模块 """ # 使用__all__控制被导入的成员 __all__ = [ 'age', 'age2', ] age = 10 age2 = 20 age3 = 30 def f1(): print('hello') # 测试函数,在开发阶段,对本模块中的功能进行测试 def main(): print(age) f1() # 可以快速生成 if __name__ == '__main__': main() # 资深程序员应该写的: # def main(): # pass # # if __name__ == '__main__': # main()
""" 导入模块的多种方式: """ # 把自定义模块的路径添加到sys.path中 import os import sys sys.path.append(os.path.dirname(__file__) + '/aa') # 使用import xxx 导入 # import my_module # print(my_module.age) # 使用from。。。import xxx的方式导入 # age = 1000 # from my_module import age # print(age) # 使用别名避免命名冲突 # from my_module import age as a # age = 1000 # print(age) # print(a) # 给模块起别名 # import my_module as m # print(m.age) # m.f1() # 验证__all__控制的成员 # from my_module import * # print(m.age) # print(m.age2) # 使用如下方式,可以绕过__all__的限制 # import my_module as m # # print(m.age) # print(m.age2) # print(m.age3)
6.import xxx 和 from xxx import * 的区别
第一种方式在使用其中成员时,必须使用模块名作为前缀。不容易产生命名冲突。
第二种方式在使用其中成员时,不用使用模块名作为前缀,直接使用成员名即可。但是容易产生命名冲突。在后定义的成员生效(把前面的覆盖了。)
7.怎么解决名称冲突的问题
-
改用import xxx这种方式导入。
-
自己避免使用同名
-
使用别名解决冲突
8.使用别名:alias
给成员起别名,避免名称冲突。
from my_module import age as a
给模块起别名,目的简化书写。
import my_module as m
9.from xxx import * 控制成员被导入
默认情况下,所有的成员都会被导入。
__all__
是一个列表,用于表示本模块可以被外界使用的成员。元素是成员名的字符串。
注意:
__all__
只是对from xxx import *这种导入方式生效。其余的方式都不生效。
10.相对导入
针对某个项目中的不同模块之间进行导入,称为相对导入。
只有一种格式:
from 相对路径 import xxx
相对路径:包含了点号的一个相对路径。
. 表示的是当前的路径。
..表示的是父路径。
...表示的是父路径的父路径。
# 相对导入同项目下的模块 # from ..z import zz # 容易向外界暴露zz模块 from ..z.zz import *
# 不使用相对导入的方式,导入本项目中的模块 # 通过当前文件的路径找到z的路径 import os import sys sys.path.append(os.path.dirname(os.path.dirname(__file__)) + '/z') from zz import *
""" 项目中,子模块 """ age = 10 def f(): print('hello')
""" 次模块作为对外引用的入口 """ # 相对导入同项目下的模块 # from ..z import zz # 容易向外界暴露zz模块 # from . import abc # 导入同路径下的abc模块 from ..z.zz import * # 不使用相对导入的方式,导入本项目中的模块 # 通过当前文件的路径找到z的路径 # import os # import sys # sys.path.append(os.path.dirname(os.path.dirname(__file__)) + '/z') # from zz import * # 定义自己的成员 age2 = 888 def f2(): print('f2')
""" 测试相对导入 """ import os import sys # 把项目所在的父路径加到sys.path中 sys.path.append(os.path.dirname(__file__)) from xx.y import yy print(yy.age2) yy.f2() # print(yy.zz.age) # yy.zz.f() print(yy.age) yy.f() # from xx.y.yy import * # # print(age2) # f2()
11.常用模块:random
此模块提供了和随机数获取相关的方法:
-
random.random():获取[0.0,1.0)范围内的浮点数
-
random.randint(a,b):获取[a,b]范围内的一个整数
-
random.uniform(a,b):获取[a,b)范围内的浮点数
-
random.shuffle(x):把参数指定的数据中的元素打乱。参数必须是一个可变的数据类型。
-
random.sample(x,k):从x中随机抽取k个数据,组成一个列表返回。
""" random模块的演示 """ import random # 获取[0.0,1.0)范围内的浮点数 # print(random.random()) # # # 获取[a,b)范围内的浮点数 # print(random.uniform(3,5)) # # # 获取[a,b]范围内的一个整数 # print(random.randint(3,10)) # lst = list(range(10)) # random.shuffle(lst) # print(lst) t = (1,2,3) # random.shuffle(t) # 通过sample变相实现打乱 lst = random.sample(t,len(t)) print(lst)
四.今日总结