闭包函数和装饰器
13.1.1 闭包函数
-
闭:封闭,关闭
-
包:包装起来的函数,对函数进行处理的数据,内层函数。
(1)闭包函数的构成条件
-
一定要是嵌套函数
-
内层函数要返回给外层函数
-
内层函数要使用外层函数的变量
(2)闭包的作用
-
可以写装饰器
-
可以保存外部函数的变量
语法格式: def out(): name = 0 def inner(): pass return inner ----------------------------- 当函数调用的时候里面的代码执行,执行完毕之后随后变量销毁 def out(): a = 10 def inner(b): nonlocal a a+=b print(a) return inner res = out() res(10) res(10) res(10) ----------------------------------- def out(name): def inner(msg): print(f'{name}:{msg}') return inner heihei = out('嘿嘿') student = out('李广') heihei('出来玩最重要的是什么?') student('不知道!') heihei('出来玩最重要的是出来') student('好的我这就出来')
-
函数内部定义的变量可以访问外层函数的变量(参数)
-
闭包的作用
-
封闭数据:将数据封装起来形成独立的作用域,避免全局变量的污染,提高代码安全性
-
保持状态,闭包可以保持外层函数的状态,即使外部函数执行完毕,闭包仍然可以访问外层函数的变量或者数据
-
实现装饰器:闭包装饰器。本质上就是一个闭包。
13.2.1 装饰器
装饰器:本质上就是一个闭包
作用:在不修改代码的前提下,给另外的函数添加新的功能,并且可以反复使用。
-
def fly(someone): wings = 0 def install(): nonlocal wings wings+=1 someone() print(f'我用有{wings}双翅膀') return install @fly def hello(): print('大家好我是周杰伦') hello() @fly def hello1(): print('大家好我是heihei') hello1() # res = fly(hello) # res() 语法糖:@+外层函数的函数名 ------------------------------------------------------ 写一个装饰器,判断函数运行的时间 import time # print(time.time()) def runtime(fun): def timer(): time_s = time.time() fun() time_res=time.time()-time_s print(f'函数运行的时间是{time_res}秒') return timer @runtime def func1(): for i in range(1000001): print(i) func1() # res = runtime(func1) # res() ----------------------------------------------------- def verify(login): def inner(): b = login() if len(b) == 11: if b.isdigit(): print('登录成功') else: print('登录失败,电话必须是纯数字,请重新登录') login() else: print('登录失败,电话必须是11位,重新登录') login() return inner @verify def phone(): a = input('请输入电话号码') return a phone()
13.3.1 带参装饰器
1 装饰器内层函数有参数的时候,被装饰函数没有参数的时候,可以通过被装饰函数给内层函数传参数。 def func(num): n = 10 def hello(a): nonlocal n num() n+=a print(n) return hello @func def qiuhe(): print('年龄是') qiuhe(10) 2被装饰函数有参数和返回值的时候,装饰器内层函数和内层函数里面的函数都要有参数和返回值。 def func(qiuhe): n = 10 def hello(name): nonlocal n qiuhe(name) n+=1 print(n) return hello @func def qiuhe(name): print(f'{name}的年龄是') qiuhe('tunk') 3 为了代码复用 万能用法 def func(qiuhe): n = 10 def hello(*args,**kwargs): nonlocal n qiuhe(*args,**kwargs) n+=1 print(n) return hello @func def qiuhe(name): print(f'{name}的年龄是') qiuhe('tunk')
小练习:
写一个装饰器,让函数重复执行5次 装饰器---把被装饰函数传到 闭包内 结合闭包内的代码增加新的功能。 for 循环 运行函数5次就行 --------- 写装饰器 1写好闭包模版 2给外层函数写参数把被装饰函数传入闭包在闭包里面调用。 3设计代码给被装饰函数添加功能 4注意内层函数的参数怎么写 5写语法糖 6直接调用被装饰的函数
答案:
def fun(num): def fun1(): for i in range(1,6): num() return fun1 @fun def handsome(): print('我是大帅哥!!!') handsome()