python全栈开发 * 12 知识点汇总 * 180530
12 知识点总结 装饰器进阶
⼀. 通⽤装饰器的回顾
1.开闭原则: 对增加功能开放. 对修改代码封闭
2.装饰器的作⽤: 在不改变原有代码的基础上给⼀个函数增加功能
3.通⽤装饰器的写法:
def wrapper(fn):
def inner(*args,**kwargs):
print("目标函数前一行")
ret=fn(*args,**kwargs)
print("目标函数后一行")
return ret
return inner
@wrapper
def target_func(*args,**kwargs):
print("我是目标函数体")
target_func()
4.执⾏过程:
(1) 程序从上向下, 当执⾏到@wrapper的时候. 把函数作为参数传递给wrapper函数. 得到inner函数. 重新赋值给target_func
(2) 当执⾏到target_func的时候. 我们实际上执⾏的是inner函数. inner函数会先执⾏⽬标函数之前的代码. 然后再执⾏你的⽬标函数. 执⾏完⽬标函数最后执⾏的是⽬标函数
之后的代码
⼆. 函数的有⽤信息
1. 如何给函数添加注释 用三个引号来表示
def eat(food,drink):
""" eat:把传递进来的吃掉
:param food: 参数food是什么意思
:param drink: 参数drink是什么意思
:return: None 返回什么
"""
print(food,drink)
return "very good"
按住ctrl 点内置函数名,可以查看函数的注释如int,str 等
2.如何获取到函数的相关信息
def eat(food,drink):
"""
:param food: 参数food是什么意思
:param drink: 参数drink是什么意思
:return: None 返回什么
"""
print(food,drink)
# print(eat.__name__) 读取不出来
# print(eat.__doc__) 读取不出来
return "very good"
eat("水果","可乐")
print(eat.__name__) # 查询函数名
print(eat.__doc__) #查询函数文档注释 函数名.__name__可以查看函数的名字 (双下划线)
函数名.__doc__ 可以查看函数的⽂档注释
(1) 一个被装饰器装饰过的函数:查询目标函数的函数名
def wrapper(fn):
def inner(*args,**kwargs): # 聚合
print("目标函数前一行")
ret=fn(*args,**kwargs) # 打散 这⾥的作⽤. 其实就是为了保证我可以装饰所有函数⽽准备的
print("目标函数后一行")
return ret
return inner
@wrapper
def target_func(*args,**kwargs):
print("我是目标函数体")
target_func()
print(target_func.__name__) # 被装饰过的函数函数名是inner.
(2) 把上述查询函数名修改为原函数名
from functools import wraps # 加 引入函数模块
def wrapper(fn):
@wraps(fn) # 加 使用函数原来的名字
def inner(*args,**kwargs):
print("目标函数前一行")
ret=fn(*args,**kwargs)
print("目标函数后一行")
return ret
return inner
@wrapper
def target_func(*args,**kwargs):
print("我是目标函数体")
target_func()
print(target_func.__name__) # 查询结果不再是inner 而是target_func
@wrapper
def new_target_func():
print("我是另⼀个⽬标函数")
new_target_func()
print(new_target_func.__name__)
三.装饰器传参
def wrapper_out(flag):
def wrapper(fn):
def inner(*args,**kwargs):
if flag==True: # 设定条件,满足执行下一步
print("目标函数前一行")
ret=fn(*args,**kwargs)
print("目标函数后一行")
else: # 不满足执行这一步
ret=fn(*args,**kwargs)
return ret
return inner
return wrapper
@wrapper_out(True)
def target_func():
print("我是目标函数体")
target_func() # 目标函数前一行,我是目标函数体,目标函数后一行
@wrapper_out(False)
def target_func():
print("我是目标函数体")
target_func() # 我是目标函数体
执行步骤: 先执⾏wrapper(True) 然后再@返回值. 返回值恰好是wrapper. 结果就是@wrapper
四.多个装饰器装饰一个函数
def wrapper(fn):
def inner(*args,**kwargs):
print("我是a")
ret=fn(*args,**kwargs)
print("我是b")
return ret
return inner
def wrapper1(fn):
def inner(*args,**kwargs):
print("我是c")
ret=fn(*args,**kwargs)
print("我是d")
return ret
return inner
def wrapper2(fn):
def inner(*args,**kwargs):
print("我是e")
ret=fn(*args,**kwargs)
print("我是f")
return ret
return inner
@wrapper2
@wrapper1
@wrapper
def eat(*args,**kwargs):
print("我是目标函数")
eat()
执行步骤:
执⾏顺序:
⾸先@wrapper1装饰起来. 然后获取到⼀个新函数是wrapper1中的inner.
然后执⾏@wrapper2.这个时候. wrapper2装饰的就是wrapper1中的inner. 第⼆层装饰器前(第⼀层装饰器前(⽬标)第⼀层装饰器后)第⼆层装饰器后. 程序从左到右执⾏
五.补充知识点
1枚举 (同时拿元素和索引)
lst=["金","木","水","火","土"]
for index,element in enumerate(lst):
print(index,element) # 解构
for element in enumerate(lst):
print(element) # 结果是元组(0,"金)
2.存盘 , 网络传输
s="提前祝大家端午节快乐"
bys=s.encode("UTF-8") # 编码
print(bys) # 结果 字节
s1=bys.decode("UTF-8") # 解码
print(s1) # 结果 字符串
应用: 把UTF-8 转成 GBK
bys=b'\xe6\x8f\x90' # 一个字符的utf-8 形式
s=bys.decode("UTF-8") # 用UTF-8 解码成 字符串s
gbk=s.encode("GBK") # 再把字符串转化成GBK (两个字节)
print(gbk) # 结果 b'\xcc\xe1'
作业:
1.给每个函数写一个记录日志的功能,功能要求:每一次调用函数之前,要将函数名称,时间节点记录到log的日志中
所需模块
import time
struct_time = time.localtime()
# localtime() : localtime是 把从1970-1-1零点零分到当前时间系统所偏移的秒数时间转换为本地时间
print(time.strftime("%Y-%m-%d %H:%M:%S",struct_time))
# strftime是一种计算机函数,根据区域设置格式化本地时间/日期,函数的功能将时间格式化,或者说格式化一个时间字符串
import time
struct_time = time.localtime()
print(time.strftime("%Y-%m-%d %H:%M:%S",struct_time))
import time
def wrapper(fn):
def inner(*args,**kwargs):
struct_time = time.localtime() #时间
f=open("log",mode="a",encoding="UTF-8") # 文件
f.write(fn.__name__+"\t"+time.strftime("%Y-%m-%d %H:%M:%S", struct_time)+"\n") #文件名和和格式化后的时间添加到文件中 ret=fn(*args,**kwargs)# 目标函数
return ret
return inner
@wrapper
def func1(*args,**kwargs):
print("函数一")
func1()
2.京东,淘宝登陆系统
# 1,用户有两套账号密码,一套为京东账号密码,一套为淘宝账号密码分别保存在两个文件中。
# 2,设置四个函数,分别代表 京东首页,京东超市,淘宝首页,淘宝超市。
# 3,启动程序后,呈现用户的选项为:
# 1,京东首页
# 2,京东超市
# 3,淘宝首页
# 4,淘宝超市
# 5,退出程序
# 4,四个函数都加上认证功能,用户可任意选择,用户选择京东超市或者京东首页,只要输入一次京东账号和密码并成功,则这两个函数都可以任意访问;
# 用户选择淘宝超市或者淘宝首页,只要输入一次淘宝账号和密码并成功,则这两个函数都可以任意访问. flag1 = True
flag2 = True def wrapper_out(aaa):
def wrapper(fn):
def inner(*args,**kwargs):
flag = True
global flag1,flag2
if aaa=="jd" :
while flag and flag1==True:
user=input("请输入您的用户名:")
pwd=input("请输入您的密码:")
with open("jd-user",mode="r",encoding='utf-8')as f:
for i in f.readlines():
username,password=i.strip().split(",")
if user==username and pwd==password:
print("登陆成功")
flag = False
flag1 = False
break
else:
print("登陆失败")
elif aaa=="tb":
while flag and flag2==True:
user2=input("请输入您的用户名:")
pwd2=input("请输入您的密码:")
with open("tb_user",mode="r",encoding="utf-8")as f:
for i in f.readlines():
username2,password2=i.strip().split(",")
if user2==username2 and pwd2==password2:
print("登陆成功")
flag=False
flag2=False
break
else:
print("登陆失败")
ret=fn()
return ret return inner
return wrapper @wrapper_out("jd")
def jd_index():
print("京东首页") @wrapper_out("jd")
def jd_market():
print("京东超市") @wrapper_out("tb")
def tb_index():
print("淘宝首页") @wrapper_out("tb")
def tb_market():
print("淘宝超市") def logout():
print("退出程序")
global flag1, flag2
flag1=False
flag2=False def start():
with open("菜单",mode="r",encoding="utf-8")as f:
for line in f:
print(line.strip()) def choic():
while 1:
choose=input("请输入序号;")
if choose=="1":
jd_index()
elif choose=="2":
jd_market()
elif choose=="3":
tb_index()
elif choose=="4":
tb_market()
elif choose=="5":
logout()
flag=False start()
choic()
3.明星投票系统:
# 1. ⽤户注册. 将⽤户名和密码保存在⽂件中.
# 2. 登录功能. 不需要三次登录. 正常反复⽆限登录就可以. 直到登录成功为⽌
# 3. ⽤户登录后可以查看所有明星信息. 明星信息保存在明星⽂件中.
# 例如:
# 1 林俊杰 1
# 2 周杰伦 0
# 3 ⿇花藤 0
# 第⼀位是序号, 第⼆位是名字, 第三位是得票数
# 4. 给明星进⾏投票
# 5. 每个⼈每24⼩时只能投⼀次票(扩展功能, 装饰器)
# 思路: 每次⽤户投票之后. 都从⽂件中查询⼀下⽤户上⼀次投票时间. 让⽤户上⼀
# 次投票时间和当前系统时间做时间差. 如果⼤于24⼩时. 则可以进⾏投票. 如果⼩于24⼩时,
# 则提⽰⽤户不能进⾏投票. 时间处理请⾃⾏百度.
# 使⽤知识点:
# 1. 函数, 请将以上功能尽可能的封装成函数. ⽤函数来描述每⼀个功能是我们以后开发
# 经常使⽤的⼀种写法和思路
import os
import time
def wrapper(fn):
def inner():
t = time.time()
t2 = os.path.getmtime("stra_info")
if t - t2 <86400.0:
print('24小时内不要重复登陆')
return
ret=fn()
return ret
return inner def start():
with open("main",mode="r",encoding="utf-8")as f:
for line in f.readlines():
print(line.strip())
start() def regist():
with open("user_info",mode="r+",encoding="utf-8")as f1:
for i in f1.readlines():
user=input("请输入用户名:")
pad=input("请输入密码:")
if user==i.strip().split(",")[0]:
print("该用户名已存在")
else:
with open("user_info",mode="a",encoding="utf-8")as f2:
f2.write("\n"+user+","+pad)
print("注册成功")
return
# regist() def logon ():
while 1:
username1 = input("请输入用户名:")
password1 = input("请输入密码:")
with open("user_info",mode="r",encoding="utf-8")as f3:
for i in f3.readlines():
user1,pwd1=i.strip().split(',') if username1==user1 and password1==pwd1:
print("登陆成功")
return
else:
print("登陆失败请重新登陆")
# logon() def star_info():
with open("star_info", mode="r",encoding="utf-8")as f4:
for line in f4.readlines():
print(line.strip()) @wrapper
def vote():
vote_num=input('请输入明星id:')
with open("stra_info",mode="r",encoding="utf-8")as f5,open("star_info1",mode="w",encoding="utf-8")as f6:
for line in f5.readlines():
num,name,poll=line.strip().split(" ")
if vote_num==num: f6.write(num+" "+name+" "+str(int(num)+1)+'\n')
else:
f6.write(line)
os.remove("stra_info")
os.rename("star_info1","stra_info") def logout():
print('您已退出系统') def choice():
while 1:
choose=input('请输入项目序号:')
if choose=="1":
regist()
elif choose=="2":
logon()
elif choose=="3":
star_info()
elif choose=="4":
vote()
elif choose=="5":
logout()
start()
choice()
python全栈开发 * 12 知识点汇总 * 180530的更多相关文章
- python全栈开发 * 01知识点汇总 * 180530
一 python简介. 1.创始人: 吉多 .范罗苏姆 \ (Guido van Rossum). 2.时间 : 1989年. 3.主要应用领域 : 云计算 \ WEB开发 \ ...
- python全栈开发 * 14 知识点汇总 * 180530
14 生成器表达式 内置函数# 一.迭代器 (补充)# 1.如何判断迭代对象,迭代器# (1).dir(obj)检测对象有没有iter方法,然后it=obj.__iter__() 获取迭代器 , it ...
- python全栈开发 * 10知识点汇总 * 180612
10 函数进阶 知识点汇总 一.动态参数 形参的第三种1.动态接收位置传参 表达:*args (在参数位置编写 * 表⽰接收任意内容) (1)动态位置参数def eat(*args): print(a ...
- python全栈开发 * 32知识点汇总 * 180717
32 网络编程 (一)一.架构 定义:程序员开发的一种模式. 分类: C/S 架构 C/S即:Client与Server , 客户端/ 服务器模式 . 缺点 : 冗余 B/S 架构 Browser与S ...
- python全栈开发 * 27知识点汇总 * 180710
27 time os sys 模块 time 模块 一.表示时间的三种方式 时间戳(timestamp), 元组(struct_time),格式化时间字符串(Format string) 小 ...
- python全栈开发 * 26知识点汇总 * 180709
26 logging collections random 模块 一.logging低配:日志不能写入文件与显示同时进行 import logging logging.basicConfig(leve ...
- python全栈开发 * 36知识点汇总 * 180721
36 操作系统的发展史 进程一.手工操作--穿孔卡片 1.内容: 程序员将对应于程序和数据的已穿孔的纸带(或卡片)装入输入机,然后启动输入机把程序和数据输入计算机内存,接着通过控制 台开关启动程序针对 ...
- python全栈开发 * 31知识点汇总 * 180716
31 模块和包一.模块(一)模块的种类:内置模块,自定义模块,扩展模块第三方模块(二)自定义模块 1.模块的创建 : 新建一个py文件. 2.模块名 : 模块名需要符合变量的命名规范. 3.模块的导入 ...
- python全栈开发 * 24 知识点汇总 * 180705
24 模块-------序列化一.什么是模块 模块:py文件就是一个模块.二.模块的分类:(1)内置模块 (登录模块,时间模块,sys模块,os模块)(2)扩展模块 (itchat 微信有关,爬虫,b ...
随机推荐
- requirejs amd module load example
person.js /** * This example make use of requireJS to provide a clean and simple way to split JavaSc ...
- NYOJ127 星际之门(一)【定理】
星际之门(一) 时间限制:3000 ms | 内存限制:65535 KB 难度:3 描写叙述 公元3000年,子虚帝国统领着N个星系,原先它们是靠近光束飞船来进行旅行的,近来,X博士发明了星际之门 ...
- [Python设计模式] 第24章 加薪审批——职责链模式
github地址:https://github.com/cheesezh/python_design_patterns 题目 用程序模拟以下情景 员工向经理发起加薪申请,经理无权决定,需要向总监汇报, ...
- Webhook 实践 —— 自动部署
https://segmentfault.com/a/1190000007892407 安装nodejs 安装nodejs建议直接下载二进制包,把官网上的64位二进制版本下载地址复制下来,执行 wge ...
- 微信小程序--canvas画布实现图片的编辑
技术:微信小程序 概述 上传图片,编辑图片大小,添加文字,改变文字颜色等 详细 代码下载:http://www.demodashi.com/demo/14789.html 概述 微信小程序--ca ...
- MySQL遇到Deadlock found when trying to get lock,解决方案
最近遇到一个MYSQL update语句出现Deadlock found when trying to get lock的问题,分析一下原因. 什么情况下会出现Deadlock found when ...
- python中的__new__与__init__,新式类和经典类(2.x)
在python2.x中,从object继承得来的类称为新式类(如class A(object))不从object继承得来的类称为经典类(如class A()) 新式类跟经典类的差别主要是以下几点: 1 ...
- 在mysql命令行下执行sql文件
***********在mysql命令行下执行sql文件*********** C:\Windows\system32>cd E:\MySQL\mysql-5.7.16-winx64\bin / ...
- ffmpeg中av_log的实现分析
[时间:2017-10] [状态:Open] [关键词:ffmpeg,avutil,av_log, 日志输出] 0 引言 FFmpeg的libavutil中的日志输出的接口整体比较少,但是功能还是不错 ...
- layer 关闭当前弹出层
关闭当前框的弹出层 layer.close(layer.index); 刷新父层 parent.location.reload(); // 父页面刷新 关闭iframe 弹出的全屏层 var inde ...