装饰器,包与模块,常用库
一.装饰器
- 在编程中有两个原则是要遵守的,也就是开放和封闭的原则
- 开发:对现有功能的拓展开放
- 封闭:已实现的功能代码不应该被修改
- 如果我们的代码中有N个函数,我们需要在这N个函数中增加或者减少一个功能,那么就意味我们需要把相同的代码增加多次或者减少多次,这样就很不符合编程开放跟封闭的原则,而且也不是一个好的编程风格,解决这样问题的思路就是装饰器
- 有一个登录,查看数据,查看钱包的代码如下:
dict1={"isLogon":False} def logon(): '''登录''' username=input("输入账号:\n") password=input("输入密码:\n") if username=="tang" and password=="123": dict1["isLogon"]=True print("登录成功") else: print("登录失败") def order(): '''查看数据''' if dict1["isLogon"]: print("已授权查看后台数据") else: print("请先登录") def admin(): '''查看钱包''' if dict1["isLogon"]: print("已授权查看钱包") else: print("请先登录") while True: a=int(input("1.登录 2.查看数据 3.查看钱包 4.退出\n")) if a==1: logon() elif a==2: order() elif a==3: admin() elif a==4: break
按照现在的代码,如果我们需要更改登录代码的判断,·那我们后面查看数据跟查看钱包的代码都要更改,我们现在需要装饰器解决这个问题
dict1={"isLogon":False} #标识 def outer(func): def inner(): #内部函数 if dict1["isLogon"]: #这里的函数就相当于if dict1["isLogon"]==True return func() else: print("请先登录") return inner #返回执行函数inner def logon(): '''登录''' username=input("输入账号:\n") password=input("输入密码:\n") if username=="tang" and password=="123": dict1["isLogon"]=True #满足如果条件的话,会把字典dict1的value值改为True print("登录成功") else: print("登录失败") @outer def order(): '''查看数据''' print("已授权查看后台数据") @outer def admin(): '''查看钱包''' print("已授权查看钱包") while True: a=int(input("1.登录 2.查看数据 3.查看钱包 4.退出\n")) if a==1: logon() elif a==2: order() elif a==3: admin() elif a==4: break
- 执行的顺序为:
- 执行outer函数
- 执行内部函数inner
- 执行inner函数的返回值
- 执行inner函数里面的表达式
- ?旦结合装饰器后,调?fun其实执?的是inner函数内部,原来的fun被覆盖
- ?旦这个函数被装饰器装饰之后,被装饰的函数重新赋值成装饰器的内层函数
二.包package与模块module
已知现有一个包test,里面有两个模块(login.py跟logout.py)
def func(): print("世界你好") list1=["hello world"]logout
-
在同一个包下,一个模块login.py怎么引用另一个模块的代码logout.py
- import导入 具体为:import导入package包.module模块
import test.logout #先导入另外一个模块 '''调用其他模块里面的函数''' test.logout.func() '''调用其他模块里面的变量''' print(test.logout.list1)
输出:
世界你好 ['hello world']
- from package包.module模块 import *(所有)函数/变量/类
from test.logout import * func() print(list1)
输出:
世界你好 ['hello world']
-
不同包之间的不同模块调用
from package包.module模块 import *(所有)函数/变量/类
-
包和包嵌套之间的调用
from package包.package包.module模块 import *(所有)函数/变量/类
三.常用库
-
标准库:安装了python的解释器,解释器内部自带的
1.os库/模块(operation system,操作系统)用于实现访问操作系统等相关的功能
-
-
- 获取当前库所在本地磁盘路径
import os #导入库 print(os.path.dirname(__file__))
输出:
F:\python\code\testdev\函数\常用库
- 获取当前库所在本地磁盘路径的上一级目录
import os #导入库 print(os.path.dirname(os.path.dirname(__file__)))
输出:
F:\python\code\testdev\函数
- 输入控制台的命令(如查看IP地址)
import os #导入库 print(os.system("ipconfig"))
- 获取本地磁盘目录下所有的文件
import os #导入库 for item in os.listdir("C:/"): print(item)
- 获取当前的操作系统
import os #导入库 print(os.name)
- 路径的拼接——>自动获取路径——>读取文件
import os base_dir=os.path.dirname(os.path.dirname(os.path.dirname(__file__))) #获取文件所在的目录并定义为变量 userPath=os.path.join(base_dir,"test","user.txt") f=open(userPath,"r",encoding="utf-8") print(f.read()) f.close()
- 获取当前库所在本地磁盘路径
-
2.time库(time库能够表达计算机时间,提供获取系统时间并格式化输出的方法,提供系统级精确计时功能(可以用于程序性能分析)。)
格式化字符串 | 日期/时间说明 | 取值范围 |
%Y | 年份 | 0000~9999 |
%m | 月份(数字) | 01~12 |
%B | 月份(英文全称) | January~December |
%b | 月份(英文缩写) | Jan~Dec |
%d | 日期 | 01~31 |
%A | 星期(英文全称) | Monday~Sunday |
%a | 星期(英文缩写) | Mon~Sun |
%H | 小时(24小时制) | 00~23 |
%I | 小时(12小时制) | 01~12 |
%p | 上/下午 | AM,PM |
%M | 分钟 | 00~59 |
%S | 秒 | 00~59 |
-
-
-
时间戳:
JavaScript时间戳:是指格林威治时间1970年01月01日00时00分00秒(北京时间1970年01月01日08时00分00秒)起至现在的总毫秒数。
Unix时间戳:是指格林威治时间1970年01月01日00时00分00秒(北京时间1970年01月01日08时00分00秒)起至现在的总秒数。 -
获取当前时间戳:
import time as t #导入time库别名为t print("获取当前时间戳:",t.time())
输出:
获取当前时间戳: 1637913653.626496
-
获取当前时间的字符串格式
import time as t #导入time库别名为t print("获取当前时间的字符串格式:",t.ctime())
输出:
获取当前时间的字符串格式: Fri Nov 26 16:01:22 2021
-
时间戳转为字符串
import time as t #导入time库别名为t print("时间戳转为字符串:",t.ctime(t.time())))
输出:
时间戳转为字符串: Fri Nov 26 16:02:12 2021
-
时间戳转为struct_time
import time as t #导入time库别名为t print("时间戳转为struct_time:",t.gmtime(t.time()).tm_year)
输出:
时间戳转为struct_time: 2021
-
时间戳转为本地时间
import time as t #导入time库别名为t print("时间戳转为本地时间:",t.localtime(t.time()))
输出:
时间戳转为本地时间: time.struct_time(tm_year=2021, tm_mon=11, tm_mday=26, tm_hour=16, tm_min=5, tm_sec=51, tm_wday=4, tm_yday=330, tm_isdst=0)
-
获取中国时间
import time as t #导入time库别名为t print("获取中国时间:",t.strftime("%y-%m-%d %H:%M:%S",t.localtime()))
输出:
获取中国时间: 21-11-26 16:11:11
-
-
3.datetime库(相比较time的模块,datetime也是表示时间的,但是会更加直观)
-
-
-
获取当前时间
import datetime print("获取当前时间:",datetime.datetime.now())
输出:
获取当前时间: 2021-11-26 16:19:02.385842
-
时间戳转换格式
import datetime import time print("时间戳转换格式:",datetime.datetime.fromtimestamp(time.time()))
输出:
时间戳转换格式: 2021-11-26 16:20:07.197038
-
在当前时间增加或减少
import datetime print("在当前时间增加8小时:",datetime.datetime.now()+datetime.timedelta(hours=8)) print("在当前时间减少2小时:",datetime.datetime.now()+datetime.timedelta(hours=-2))
输出:
在当前时间增加8小时: 2021-11-27 00:21:38.241342 在当前时间减少2小时: 2021-11-26 14:21:38.241342
-
-
4.json库
-
-
-
序列化和反序列化:
序列化:把内存里的数据类型转为字符串的数据类型,使能够存储到硬盘或通过网络传输到远程,因为硬盘或 者网络传输时只接受bytes的数据类型。简单的说就是把Python的数据类型(字典,元组,列表)转为str的数据类型过程
反序列化,就是str的数据类型转为Python对象的过程。 -
函数
针对python对象 dumps() 对Python对象(list,tuple,dict)进行序列化 loads() 对Python对象(list,tuple,dict)进行反序列化 针对python文件 dump() 对文件进行序列化(本质上把内容写到文件里面) load() 对文件进行反序列化(本质上是读取文件里面的内容) -
列表的序列化和反序列化
import json list1=["hello","world",1,2] #序列化 listStr=json.dumps(list1) print(listStr) print(type(listStr))
#反序列化 strList=json.loads(listStr) print(strList) print(type(strList))
输出:
["hello", "world", 1, 2] <class 'str'> ['hello', 'world', 1, 2] <class 'list'>
-
元组的序列化和反序列化(元组反序列化之后会变成列表的数据类型)
import json tuple=("C","Python","Java") #元组的序列化 tupleStr=json.dumps(tuple) print(tupleStr) print(type(tupleStr))
#元组的反序列化(元组反序列化之后会变成列表的数据类型) strTuple=json.loads(tupleStr) print(strTuple) print(type(strTuple))
输出:
["C", "Python", "Java"] <class 'str'> ['C', 'Python', 'Java'] <class 'list'>
-
字典的序列化和反序列化
import json dict1={"name":"tang","city":"xian"} #序列化 dictStr=json.dumps(dict1) print(dictStr) print(type(dictStr))
#反序列化 strDict=json.loads(dictStr) print(strDict) print(type(strDict))
输出:
{"name": "tang", "city": "xian"} <class 'str'> {'name': 'tang', 'city': 'xian'} <class 'dict'>
字典在序列化如果有汉字时如果dict包含有汉字,一定加上ensure_ascii=False。否则按参数默认值True,意思是保证dumps之后的结果里所有的字符都能够被ascii表示,汉字在ascii的字符集里面,因此经过dumps以后的str里,汉字会变成对应的unicode
-
-
-
-
-
文件的序列化和反序列化
import json dict1= {"name": "tang", "city": "西安"} #序列化 json.dump(dict1,open("index.txt","w"))
#反序列化 print(json.load(open("index.txt","r"))) print(type(json.load(open("index.txt","r"))))
输出:
{'name': 'tang', 'city': '西安'} <class 'dict'>
-
-
-
-
-
文件的序列化和反序列化本质上跟文件的读取没有区别
-
-
现在有一个结合文件读取的注册登录代码如下:
1 def out(): 2 username = input("输入账号:\n") 3 password = input("输入密码:\n") 4 return username,password 5 def register(): 6 '''注册''' 7 username,password=out() 8 temp=username+"|"+password 9 temp=username+"|"+password 10 f=open("user.txt","w") 11 f.write(temp) 12 f.close() 13 print("注册成功") 14 def login(): 15 '''登录''' 16 username,password=out() 17 f=open("user.txt","r") 18 list1=f.read().split("|") 19 f.close() 20 if username==list1[0] and password==list1[1]: 21 print("登录成功") 22 else: 23 print("账号密码错误") 24 if __name__ == '__main__': 25 while True: 26 a = int(input("1.注册 2.登录 3.退出\n")) 27 if a == 1: 28 register() 29 elif a == 2: 30 login() 31 elif a == 3: 32 break注册登录
同样我们可以使用文件的序列化跟反序列化来完成:
import json def out(): username = input("输入账号:\n") password = input("输入密码:\n") return username,password def register(): '''注册''' username,password=out() temp=username+"|"+password json.dump(temp,open("user.txt","w")) print("注册成功") def login(): '''登录''' username,password=out() list1=str(json.load(open("user.txt","r"))).split("|") print(type(list1)) if username==list1[0] and password==list1[1]: print("登录成功") else: print("账号密码错误") if __name__ == '__main__': while True: a = int(input("1.注册 2.登录 3.退出\n")) if a == 1: register() elif a == 2: login() elif a == 3: break
5.sys库
-
-
-
定义:
-
-
Python的sys模块提供访问由解释器使用或维护的变量的接口,并提供了一些函数用来和解释器进行交互,操控Python的运行时环境。
-
-
-
查看python解释器版本
import sys print(sys.version)
输出结果:
3.9.5 (tags/v3.9.5:0a7dcbd, May 3 2021, 17:27:52) [MSC v.1928 64 bit (AMD64)]
-
查看解释器所在本地路径
import sys for item in sys.path: print(item)
输出结果:
F:\python\code\testshare\练习\share F:\python\code\testshare F:\Python3\python39.zip F:\Python3\DLLs F:\Python3\lib F:\Python3 F:\Python3\lib\site-packages
-
查看操作系统
import sys print(sys.platform)
输出结果:
win32
-
搜索模块的路径集
import sys print(sys.path)
输出结果:
['F:\\python\\code\\testshare\\练习\\share', 'F:\\python\\code\\testshare', 'F:\\Python3\\python39.zip', 'F:\\Python3\\DLLs', 'F:\\Python3\\lib', 'F:\\Python3', 'F:\\Python3\\lib\\site-packages']
-
在工作或者写代码的阶段,当导入的方式是正确的,但是提示模块不存在,那么这个时候我们使用sys来解决(把不存在模块的路径加到sys执行的路径中)
import os import sys #导入库 base_dir=os.path.dirname(os.path.dirname(__file__)) #查看文件上一级路径 day12Path=os.path.join(base_dir,"day12") #拼接路径 sys.path.append(day12Path) #添加到路径到sys.path中 from login import * #导入模块 func() #调用函数
-
-
6.hashlib库(md5的加密算法)
-
-
-
open api :开发平台的接口
-
open api的加密思路:
-
对请求参数进行排序,根据key来进行排序
-
把请求参数处理成key=value&key=value
-
对请求参数进行md5的加密(加密的数据类型必须是bytes的数据类型)
-
把加密后的sign当作请求头给服务端发送过去,服务层进行比较,如果一致,可以请求,如果不一致,拒绝请求
-
-
实战
import hashlib import time from urllib import parse def sign(): #定义函数 dict1={"name":"tang","age":21,"city":"xian","time":time.time()} #在字典中添加时间戳(因为时间戳是一直改变的,所以加密之后也是不一样的) data=dict(sorted(dict1.items(),key=lambda item:item[0])) #对字典的key值进行排序 data=parse.urlencode(data) #把请求参数处理成key=value&key=value m=hashlib.md5() #获取md5的对象 m.update(data.encode("utf-8")) #把str转为bytes的数据类型,进行具体的加密 return m.hexdigest() print(sign())
-
- 输出结果:
f6e9e06c2ef9b47f81d24b83da1b4448
-
-
第三方库:由很多的顶级程序员开发的,需要额外安装
-
-
安装:pip3 install 第三方库的名称
-
安装方式:打开控制台输入pip3 install 第三方库的名称即可
C:\Users\特昂糖>pip3 install flask Collecting flask Downloading Flask-2.0.2-py3-none-any.whl (95 kB) |████████████████████████████████| 95 kB 306 kB/s Collecting Werkzeug>=2.0 Downloading Werkzeug-2.0.2-py3-none-any.whl (288 kB) |████████████████████████████████| 288 kB 1.7 MB/s Collecting Jinja2>=3.0 Downloading Jinja2-3.0.3-py3-none-any.whl (133 kB) |████████████████████████████████| 133 kB 3.3 MB/s Collecting itsdangerous>=2.0 Downloading itsdangerous-2.0.1-py3-none-any.whl (18 kB) Collecting click>=7.1.2 Downloading click-8.0.3-py3-none-any.whl (97 kB) |████████████████████████████████| 97 kB 1.4 MB/s Requirement already satisfied: colorama in f:\python3\lib\site-packages (from click>=7.1.2->flask) (0.4.4) Collecting MarkupSafe>=2.0 Downloading MarkupSafe-2.0.1-cp39-cp39-win_amd64.whl (14 kB) Installing collected packages: MarkupSafe, Werkzeug, Jinja2, itsdangerous, click, flask Successfully installed Jinja2-3.0.3 MarkupSafe-2.0.1 Werkzeug-2.0.2 click-8.0.3 flask-2.0.2 itsdangerous-2.0.1 WARNING: You are using pip version 21.1.1; however, version 21.3.1 is available. You should consider upgrading via the 'f:\python3\python.exe -m pip install --upgrade pip' command.安装第三方库
-
-
卸载:pip3 uninstall 第三方库的名称
-
-
-
常用的第三方库:
pip3 install pytest(单元测试框架) pip3 install flask(轻量级web框架) pip3 install django(全栈web框架) pip3 install requests(做接口测试的库,也可以做网络爬虫) pip3 install pymysql(操作MySQL数据库) pip3 install xlrd(操作Excel) pip3 install selenium(做UI自动化测试)
-