函数-3
目录:
-
闭包函数
-
闭包函数的简介
-
闭包函数的实际应用
-
-
装饰器
- 装饰器简介
- 装饰器的前期推导
- 装饰器的各种版本
- 装饰器的固定模板
闭包函数
-
闭包函数的简介
-
定义在函数内部的函数
-
内部函数用了外部函数的名称空间中的名称
只有符合这两点才能称之为闭包函数
即 在嵌套函数中,内层函数用了外层函数的变量名
-
-
闭包函数的实际应用
-
直接把函数体需要的参数定义成形参
def foun(x) print(x) foun(1) # 1 foun(2) # 2 foun(3) # 3 -
把函数体需要的参数定义成闭包函数的形式
def foun1(x):
def foun():
print(x)
return foun
a = foun1(1/2/3)
a() # 1 2 3
装饰器
- 装饰器的简介
-
装饰器的本质
在不改变被装饰对象原来的'调用方式'和'内部代码'的情况下给被装饰对象添加新的功能
def func():
print(123)
func() # 每次执行之前需要校验用户身份
-
装饰器的原则
对修改封闭 对扩展开放
能添加功能,但不能修改代码
-
知识储备
import time
1.统计代码的运行时间
# print(time.time()) # 1656987566.7260265
'''时间戳(秒数):当前距离1970年1月1日0时0分0秒所经历的秒数'''
# 实际应用>>>:统计代码的运行时间
# start_time = time.time() # 100
# for i in range(100000):
# print(i)
# end_time = time.time()
# print('for循环的执行时间是:%s'%(end_time - start_time))
2. 让程序原地等待
time.sleep(3)
'''让程序原地等待三秒'''
print('睡醒了 还是很蒙蔽')
- 装饰器的前期推导
import time
def index():
time.sleep(3)
print('from index')
'''统计index函数的执行时间'''
# start_time = time.time() # 在调用index函数之前获取一下时间戳
# index() # 调用index函数
# end_time = time.time()
# print(end_time - start_time)
"""
缺陷
如果有多个index需要统计时间 则需要重复编写代码
解决措施:
封装成函数
"""
# def get_time():
# start_time = time.time() # 在调用index函数之前获取一下时间戳
# index() # 调用index函数
# end_time = time.time()
# print('函数的执行时间是:',end_time - start_time)
"""
缺陷
如果有多个不同的函数需要统计时间 那么上述的解决措施不够完善
解决措施:
给函数体添加形参(动态传参)
"""
def home():
time.sleep(5)
print('from home')
def get_time(xxx):
start_time = time.time() # 在调用index函数之前获取一下时间戳
xxx(*args,**kwargs) # 调用index函数
end_time = time.time()
print('函数的执行时间是:',end_time - start_time)
# get_time(index)
# get_time(home)
"""
缺陷
不同形参个数的函数无法兼容统计
解决措施:
*args **kwargs
但是在我们目前的代码中无法实现(暂且忽略)
"""
def func1(a):
time.sleep(1)
print('from func1')
get_time(func1)
"""
缺陷
改变了原来的调用方式
解决措施:
装饰器推导流程
"""
- 装饰器的各种版本
import time
"""针对有参无参函数如何兼容"""
def outer(xxx):
def get_time(*args, **kwargs):
start_time = time.time() # 在调用index函数之前获取一下时间戳
res = xxx(*args, **kwargs) # 调用index函数
end_time = time.time()
print('函数的执行时间是:', end_time - start_time)
return res
return get_time
def home():
time.sleep(2)
print('from home')
return '执行home函数之后的返回值'
def index(name):
time.sleep(1)
print('from index')
return '执行index函数之后的返回值'
home = outer(home)
xxx = home()
print(xxx)
index = outer(index)
res = index('jason')
print(res)
# home = outer(home)
# home()
# def func(a,b,c):
# time.sleep(1)
# print('from func')
#
# index = outer(index)
# index('jason')
#
# home = outer(home)
# home()
#
# func = outer(func)
# func(1,2,3)
- 装置器的固定模板
from functools import wraps
def outer(func_name):
@wraps(func_name) # 仅仅是为了让装饰器不容易被别人发现 做到真正的以假乱真
def inner(*args, **kwargs):
print('执行被装饰对象之前可以做的额外操作')
res = func_name(*args, **kwargs)
print('执行被装饰对象之后可以做的额外操作')
return res
return inner
# import time
# def home():
# time.sleep(1)
# print('from home')
# return 'home返回值'
# home = outer(home)
# res = home()
# print(res)
"""
执行home函数之前需要添加校验用户身份的功能
"""
# 装饰器语法糖
import time
@outer # home = outer(真正的函数名home)
def home():
'''我是home函数 我要热死了!!!'''
time.sleep(1)
print('from home')
return 'home返回值'
# help(home)
# print(home)
home()
# def index():
# '我是index函数 我的功能很强大'
# pass
#
# help(index)
作业
1.编写一个用户认证装饰器
基本要求
执行每个函数的时候必须先校验身份 eg: jason 123
拔高练习(有点难度)
执行被装饰的函数 只要有一次认证成功 那么后续的校验都通过
函数:register login transfer withdraw
提示:全局变量 记录当前用户是否认证
flag = False
def outer(approve):
def inner(*args,**kwargs):
global flag
if flag:
return approve(*args,**kwargs)
else:
username = input('请输入用户名:').strip()
password = input('请输入密码:').strip()
if username == 'jason' and password == '123':
flag = True
return approve(*args, **kwargs)
else:
print('权限不够')
return inner
@outer
def register():
"""
注册界面
:return:
"""
print('欢迎注册')
@outer
def login():
print('正在登录')
@outer
def transfer():
print('正在转移')
@outer
def withdraw():
print('正在提取')
func_dic = {
'1':register,
'2':login,
'3':transfer,
'4':withdraw
}
while True:
print("""
1.进入注册页面
2.进入登录页面
3.进入转移页面
4.进入提取页面
""")
# 获取用户输入的功能编号
func_id = input('请输入功能编号:').strip()
if func_id in func_dic:
func = func_dic.get(func_id)
func()
else:
print('没有此功能')

浙公网安备 33010602011771号