python函数3(闭包、装饰器)
python函数
一、闭包
1、函数的嵌套
如果在一个函数的内部定义了另一个函数,外部的我们叫它外函数,内部的我们叫它内函数。
2、闭包的概念
在一个外函数中定义了一个内函数,内函数里运用了外函数的临时变量,并且外函数的返回值是内函数的引用。这样就构成了一个闭包。
3、闭包的功能
def outer(a): # outer是外部函数 a和b都是外函数的临时变量
b = 10
def inner(): # inner是内函数
print(a+b) # 在内函数中 用到了外函数的临时变量
return inner # 外函数的返回值是内函数的引用
if __name__ == '__main__':
'''
在这里我们调用外函数传入参数5,此时外函数两个临时变量 a是5 b是10,
并创建了内函数,然后把内函数的引用返回存给了demo
外函数结束的时候发现内部函数将会用到自己的临时变量,
这两个临时变量就不会释放,会绑定给这个内部函数
'''
demo = outer(5)
# 我们调用内部函数,看一看内部函数是不是能使用外部函数的临时变量
# demo存了外函数的返回值,也就是inner函数的引用,这里相当于执行inner函数
demo() # 15
demo2 = outer(7)
demo2() #17
python装饰器就是用于拓展原来函数功能的一种函数,这个函数的特殊之处在于它的返回值也是一个函数,使用python装饰器的好处就是在不用更改原函数的代码前提下给函数增加新的功能。
import time
def calc_time(fn):
start_time=time.time()
fn()
end_time=time.time()
print(f'代码消耗时间:{end_time-start_time}')
def demo():
for i in range(100000):
print(i)
calc_time(demo)
在Python中,能把代码更加优化,使用装饰器。
import time
def calc_time(fn):
print('我是外函数!')
def inner():
start_time = time.time()
fn()
end_time=time.time()
print(f'代码消耗时间:{end_time-start_time}')
return inner
@calc_time
def demo():
for i in range(100000):
print(i)
demo()
执行步骤:
a、把被装饰函数demo作为参数传给装饰器(fn=demo)
b、底层执行装饰器函数(calc_time(demo))
c、装饰器函数执行完,return 内函数(inner),此时底层再次用demo来接return出来的对象(demo=inner)
d、第1—第3步骤可概况为:demo=calc_time(demo)
e、最后执行demo()即执行inner()
2、被装饰函数传参(万能装饰器)
import time
sum=0
def calc_time(fn):
def inner(*args,**kwargs):
start_time = time.time()
fn(*args,**kwargs)
end_time=time.time()
print(f'代码消耗时间:{end_time-start_time}')
return inner
@calc_time #demo=calc_time(demo)
def demo(*args,**kwargs):
global sum
for i in range(*args):
sum+=i
print(sum)
print(kwargs)
demo(33333,a=55,b=222)
3、装饰器传参
def outer(clock):
print('我是外函数')
def middle(fn):
print('我是middle函数')
def inner(*args,**kwargs):
name=args[0]
age=kwargs['age']
print('我是内函数')
print(f'外函数的参数是{clock}')
print(f'{name}今年{age}岁')
fn()
return inner
return middle
@outer(12)
def test():
print('多重装饰器的使用测试')
test('zhangsan',age=20)
运行结果:
我是外函数
我是middle函数
我是内函数
外函数的参数是12
zhangsan今年20岁
多重装饰器的使用测试
执行步骤:
a、执行outer函数,把12传递给clock,return middle对象
b、@middle就是一个装饰器,把test函数传递给fn
c、底层执行装饰器,return 内函数(inner),此时底层再次用test来接return出来的对象(test=inner)
d、test('zhangsan',age=20) 就是执行inner('zhangsan',age=20)
4、多重装饰器
def fun1(fun):
def inner_fun1():
fun()
print('----inner_fun1----')
return inner_fun1
def fun2(fun):
def inner_fun2():
fun()
print('----inner_fun2----')
return inner_fun2
@fun2
@fun1
def fun():
print('----fun----')
fun()
运行结果:
----fun---- ----inner_fun1---- ----inner_fun2----
执行步骤:
1、fun作为参数传给装饰器fun1
2、底层开始执行装饰器fun1,把内函数inner_fun1返回出来,此时fun=inner_fun1
3、再把当前的fun(inner_fun1)作为参数传给装饰器fun2
4、底层执行装饰器fun2,把内函数inner_fun2返回出来,此时fun=inner_fun2
5、开始执行fun(),实际上就是执行inner_fun2(),inner_fun2函数里有两条语句,第一条是fun(),第二条是print('inner_fun2'),而fun为2里面的inner_fun1,也就是执行inner_fun1函数
6、inner_fun1函数里也有两条语句,第一条是fun(),第二条是print('inner_fun1'),此时的fun函数即为原始的被装饰函数,因此输出的顺序为:
----fun----
----inner_fun1----
----inner_fun2----
7、使用装饰器的效果等同于:fun2(fun1(fun))()

浙公网安备 33010602011771号