景区网站建设策划方案,优化设计六年级下册数学答案,网站开发质保,湘icp备 网站建设 机械 湖南DAY 9. 闭包和装饰器
9.1 闭包 闭包就是内部函数对外部函数作用域内变量的引用 可以看出
闭包是针对函数的#xff0c;还有两个函数#xff0c;内部函数和外部函数闭包是为了让内部函数引用外部函数作用域内的变量的
我们先写两个函数
def fun1():print(我是fun1还有两个函数内部函数和外部函数闭包是为了让内部函数引用外部函数作用域内的变量的
我们先写两个函数
def fun1():print(我是fun1)def fun2():print(我是fun2)这样fun2就作为fun1的内部函数此时在函数外部是无法调用Fun2的因为
fun2实际上相当于fun1的一个属性(方法)作用域是fun1的块作用域全局作用域中无法找到函数内属性的生命周期是在函数运行期间在fun1中只是定义了fun2并没有调用它
为了让fun2跳出fun1的生命周期我们需要返回fun2这样在外部获取到的fun1的返回值就是fun2这样调用fun1的返回值就是调用了fun2,如
def fun1():print(我是fun1)def fun2():print(我是fun2)return fun2var fun1()
var()
# 我是fun1
# 我是fun2当然这还不是一个闭包闭包是引用了自由变量的函数所谓自由变量可以理解为局部变量如果fun2调用了fun1中的变量那么fun2就是一个闭包了。如
def fun1(var1):def fun2():print(fvar1 {var1})return fun2var fun1(1)
var() # var1 1闭包的作用
闭包私有化了变量实现了数据的封装类似于面向对象
def fun1(obj):def fun2():obj[0] 1print(obj)return fun2if __name__ __main__:mylist [i for i in range(5)]var fun1(mylist)var()var()var()# [1, 1, 2, 3, 4]# [2, 1, 2, 3, 4]# [3, 1, 2, 3, 4]9.2 装饰器
闭包在python中有一个重要的用途就是装饰器装饰器接受被装饰的函数作为参数并执行一次调用装饰器的本质还是一个闭包
def func1(func):def func2():print(func2)return func()return func2func1
def Demo():print(Demo)if __name__ __main__:Demo()# func2# Demo首先func1是一颗语法糖等价于func1(Demo)()外部函数必须能接收一个参数也只能接受一个参数如果有多个参数必须再套一个函数因为在使用语法糖时会自动把被修饰函数作为参数传递给装饰器内部函数必须返回被装饰函数的调用
运行流程
把被修饰函数作为参数传递给装饰器,这时函数返回的是闭包函数func2隐式地调用func2,相当于func2()执行函数体输出func2,这时函数返回值是func(),返回的直接是被修饰函数的调用相当于直接执行被修饰函数输出Demo
相当于
def func1(func):def func2():print(func2)return func()return func2# func1
def Demo():print(Demo)if __name__ __main__:# s Demo()# 先把被修饰函数作为参数传递给修饰器这里的s就是func2s func1(Demo)# 调用闭包函数s()print(s)# func2# Demo# function func1.locals.func2 at 0x00000117F163AD90
9.2.1 装饰器带参数
def func1(num):def func2(func):def func3():if num 10:print(大于10)else:print(小于10)return func()return func3return func2func1(num12)
def Demo():print(Demo)if __name__ __main__:Demo()b执行流程
将装饰器的参数传递给第一层函数并返回第二层函数func2将被修饰函数作为参数传递给第二层函数func2,隐式调用func2返回闭包函数执行闭包函数并返回被修饰函数的调用执行被修饰函数
9.2.2 被修饰函数带参数
如果被修饰函数带有参数需要把参数传递给内层闭包函数,返回被修饰函数的调用时记得加参数
def func1(func):def func2(arg):arg 1# 记得加参数return func(arg)return func2func1
def Demo(arg):print(arg)if __name__ __main__:Demo(11) # 129.2.3 例
求斐波那契数列任意一项的值
import timedef code_time(func):修饰器用来打印函数运行时间:param func: 被修饰函数:return: funcstart_time time.time()def closer(*args,**kwargs):result func(*args,**kwargs)codeTime time.time() - start_timeprint(fThis code runs at:{codeTime})return resultreturn closerdef _Fibonacci(n):if n 1:return 1else:return _Fibonacci(n-1) _Fibonacci(n-2)code_time
def Fibonacci(n):return _Fibonacci(n)if __name__ __main__:var Fibonacci(40)print(var)# This code runs at:61.738335609436035# 165580141发现代码效率非常低输出第四十个值需要一分多钟这是应为每计算一个值需要计算前两个值这里有很多重复的如 10||-----------------|9 8
|--------| |--------|
8 7 7 678被重复计算多次所以需要把已经计算过的储存起来计算之前先判断有没有计算过没计算过再计算修改程序为
import timedef code_time(func):修饰器用来打印函数运行时间:param func::return:start_time time.time()def closer(*args,**kwargs):result func(*args,**kwargs)codeTime time.time() - start_timeprint(fThis code runs at:{codeTime})return resultreturn closer
resultList {0:1,1:1}
def _Fibonacci(n):if n 1:return 1else:if n-1 in resultList:a resultList[n-1]else:a _Fibonacci(n-1)resultList[n-1] aif n-2 in resultList:b resultList[n-2]else:b _Fibonacci(n-2)resultList[n-2] breturn a bcode_time
def Fibonacci(n):return _Fibonacci(n)if __name__ __main__:var Fibonacci(40)print(var)# This code runs at:0.0# 165580141速度快了很多但重复的代码是不能忍受的使用修饰器重新一下
import timedef code_time(func):start_time time.time()def closer(*args, **kwargs):result func(*args, **kwargs)codeTime time.time() - start_timeprint(fThis code runs at:{codeTime})return resultreturn closerdef modify(func):catch {0: 1, 1: 1}def closer(*args):if args not in catch:catch[args] func(*args)return catch[args]return closermodify
def _Fibonacci(n):if n 1:return 1else:return _Fibonacci(n - 1) _Fibonacci(n - 2)code_time
def Fibonacci(n):return _Fibonacci(n)if __name__ __main__:var Fibonacci(40)print(var)
有20节楼梯一次可以走1234级总共有多少种走法
from my_python_package import code_timedef Modify(c None):if c None:c {}def modify(func):catch cdef closer(*args):if args[0] not in catch:catch[args[0]] func(*args)return catch[args[0]]return closerreturn modifyModify()
def _Stairs(num, steps):count 0if num 0:count 1elif num 0:for step in steps:count _Stairs(num-step,steps)return countcode_time
def Stairs(num,steps):count _Stairs(num,steps)return countif __name__ __main__:num 20steps [step for step in range(1,5)]count Stairs(num, steps)print(count)# Stairs runs at: 0.0 s# 2839539.3 总结 闭包内部函数调用了外部函数作用域内的变量 针对函数要有自由变量私有变量要点内部函数要跳出外部函数的生命周期需要外部函数把他return出来 装饰器 基础闭包作用不修改原来代码的基础上拓展原函数功能用处修改API功能AOP编程要点语法糖函数执行顺序 参考链接
Python高级编程技巧进阶(已完结)
Python的闭包与装饰器