闭包与认识装饰器
一、函数名
函数名在本质上就是函数的内存地址,函数名有以下功能:
函数名可以赋值给别的变量;;
函数名还可以当做容器类型里面的元素,(列表、字典);
函数名可以当做函数的参数和返回值;具体实例如下:
#!/usr/bin/python # -*- encodeing:utf-8 -*- # 函数可以赋值给别的变量 # def func(): # print('caoyf') # a = func # 此函数名赋值给了变量'a',在下面直接输入a()就相当于调用func函数 # a() #函数名可以当做容器类型的元素:例如:列表 # def func(): # print('我是func函数') # def inner(): # print('我是inner函数') # def caoyf(): # print('我是曹艳飞函数') # a = [func,inner,caoyf] # 列表的查询方式可以通过切边进行查看,为了方便查看所有结果,使用for循环一次查看所有的结果 # for i in a: # i() # 函数名可以当做函数的参数和返回值使用: # def func(): # print('func函数') # def inner(name): # name() # return name # a = inner(func) # print(a)
二、闭包
函数的闭包定义:
在函数内部再定义一个函数,并且这个函数用到了外边函数的变量,那么将这个函数以及用到的一些变量称之为闭包,实例如下:
#!/usr/bin/python # -*- encodeing:utf-8 -*- # 内部函数调用外部函数的变量 # def func(a): # def inner(b): # return a + b # 在inner函数里面调用了func函数的变量a,然后将inner返回给调用者 # return inner # ret = func(30)(20) # print(ret)
内部函数对外部函数作用域变量的引用(非全局变量),则成为内部函数为闭包,实例如下:
判断一个函数是不是闭包,可以使用__closure__方法测试,如果打印出来的是cell那这就是一个闭包,如果打印的是None,那就不是闭包,实例如下:
#!/usr/bin/python # -*- encodeing:utf-8 -*- # def func(): # name = 'caoyf' # def inner(): # print(name) # return inner # ret = func() # inner函数里面调用了func函数的变量name。 # ret() # 判断是不是闭包 # def func(): # name = 'caoyf' # def inner(): # print(name) # print(inner.__closure__) #这个函数是一个闭包,因为inner函数里面调用了func函数的变量name。 # return inner # ret = func() # ret() # def func(): # name = 'caoyf' # def inner(): # print(666666) # print(inner.__closure__) # inner() #这个函数就不是闭包,因为内部没有引用外部的变量 # ret = func()
三、装饰器
装饰器本质上就是一个python闭包函数,他可以让其他函数在不需要做任何代码变动的前提下,增加额外的功能,装饰器的返回值也是一个函数对象。
装饰器的应用场景:比如插入日志,性能测试,事务处理,缓存等等场景。
初始装饰的形成
现在有这么一个开发需求,领导想知道每段代码的耗时时间,来评比工作的考核
一般开发的代码内容如下:
#!/usr/bin/python # -*- encodeing:utf-8 -*- def func(): print('执行此段代码,你会看到意想不到的结果')
灵机一动,写了下面的代码:
#!/usr/bin/python # -*- encodeing:utf-8 -*- import time def func(): start = time.time() time.sleep(0.1) # 假设为执行时间,实际代码肯定不是一个print能搞定的 print("执行此段代码,你会看到意想不到的结果") end = time.time() print('func函数共用时%s' %(end - start)) func()
在接下来的几天时间里,开发的同事看见我都想打死我,我有赶紧的把原来的代码拿出来进行修改,于是又出来了下面的版本,同时告诉大家以后再使用的时候直接调用timeer函数就行了;
#!/usr/bin/python # -*- encodeing:utf-8 -*- # import time # def func(): # print('执行此段代码,你会看到意想不到的结果') # def timeer(func): # start = time.time() # func() # end = time.time() # print('func函数共用时%s' %(start - end)) # f1 = func # func = timeer # func(f1)
后来有人告诉我里面的代码还可以节俭,可以使用语法糖的方式,这样同事在计算时间的函数前加一句@timeer就可以了,于是又出了一个版本;
#!/usr/bin/python # -*- encodeing:utf-8 -*- import time def timeer(f): def inner(): start = time.time() f() end = time.time() print('func函数共用时%s' %(start - end)) return inner @timeer def func(): print('执行此段代码,你会看到意想不到的结果') func()
为了方便后期开发同事的使用,有修改了一次版本,增加了带有参数的和返回值的,以下是万能版本的timeer函数装饰器:
#!/usr/bin/python # -*- encodeing:utf-8 -*- import time def timeer(f): def inner(*args,**kwargs): start = time.time() ret = f(*args,**kwargs) end = time.time() print('func函数共用时%s' %(start - end)) return ret return inner @timeer def func(*args): print('执行此段代码,你会看到意想不到的结果 %s'%args) func('www.xxxooo.com')
本文来自博客园,作者:曹艳飞,转载请注明原文链接:https://www.cnblogs.com/caoyf1992/p/8411265.html