闭包和装饰器
闭包
- 两个函数的嵌套,外部函数返回内部函数的引用,并且外部函数都有参数
# 闭包的写法,两层函数的嵌套,外部函数返回内部函数的引用,外层函数都带参数
def 外层函数的名称(参数):
def 内层函数的名称():
pass
return 内层函数的引用
- 函数以及闭包之间的区别
- lambda就是完成一段简单的功能
- 函数就是完成一段功能
- 对象是多个函数跟数据的合集
- 闭包是完成一段功能时需要一个保持一个数据
nonlocal
- 功能和global功能相似,
- global指定被修饰的变量为全局
- nonlocal指定被修饰的变量不是局部
def set_fun(func):
func = 254
def call_fun():
nonlocal func # 修改外层函数的值,并且内部函数有外部函数相同的变量名
print(func)
func = 100
return call_fun
fun = set_fun(123)
fun()
装饰器
- 创建一个闭包(终级版)
- @xx装饰你要装饰的函数
万能装饰器
def set_fun(func):
def call_fun(*args,**kwargs):
return func(*args,**kwargs)
return call_fun
@set_fun
def test():
pass
- 装饰器在不改变原先的函数代码的情况下,给原先的函数添加额外的功能(原则)
- 装饰器不会去改变原函数的参数及结果
- 装饰前的函数(test),是由func指向的
- 装饰后的函数(test),是指向了call_fun
案例
# 定义函数:完成包裹数据
def makeBold(fn):
def wrapped():
return "<b>" + fn() + "</b>"
return wrapped
# 定义函数:完成包裹数据
def makeItalic(fn):
def wrapped():
return "<i>" + fn() + "</i>"
return wrapped
@makeBold
def test1():
return "hello world-1"
@makeItalic
def test2():
return "hello world-2"
@makeBold
@makeItalic
def test3():
return "hello world-3"
print(test1())
print(test2())
print(test3())
运行结果:
<b>hello world-1</b>
<i>hello world-2</i>
<b><i>hello world-3</i></b>
装饰器功能
- 引入日志
- 函数执行时间统计
- 执行函数前预备处理
- 执行函数后清理功能
- 权限校验等场景
- 缓存
案例
# 作业要求
# 设计装饰器
# 计算某函数的执行次数,用户行为分析
# 计算某函数的执行时间,优化
import random
import time
# 定义装饰器1,计算次数
def out_fun1(func):
count = 0
def inner_func():
func()
nonlocal count
# global count
count += 1
return count
return inner_func
# 定义装饰器2,计算时间
def out_fun2(func):
def inner_func():
start = time.time()
func()
end = time.time()
return end - start
return inner_func
@out_fun1
def demo():
a = 0
for x in range(1, 100001):
a += x
# print('计算100000以内的累加,结果为:', a)
@out_fun1
def demo1():
a = 1
for x in range(1,101):
a *= x
# print('计算1-100累积,结果为:', a)
@out_fun2
def test():
for x in range(100):
index = random.randint(90, 100)
if index % 2 == 0:
count = demo()
print('第', count, '次执行Demo函数')
else:
count = demo1()
print('Demo1函数,第', count, '次执行')
print('共用时', test())