Python高级--闭包与装饰器

Python高级--闭包与装饰器

前言:在Python中,闭包是一种非常有用的功能!它通常与装饰器一起搭配使用,可以在不改变被装饰函数的功能的基础上,完成更多的功能。如权限认证。

一、如何定义闭包

  1.闭包就是两个嵌套的函数,外层函数返回内层函数的引用,而且外层函数必须携带参数!为什么外层函数必须要有参数呢?可以思考一下!

  基本格式如下:  

1 def outer_fun(func):
2     def inner_fun():
3         pass
4     return inner_fun

  2.与普通函数的区别:

   闭包的外层函数的变量可以在内存中保存着,有点像类;而普通函数一旦执行完,那么就要回收内存。

  3.万能闭包

def outer_func(func):
    def inner_func(*args, **kwargs):
        func(*args, **kwargs)
    return inner_func

 

  

二、装饰器

  1.什么是装饰器:@闭包的外层函数名

  2.装饰器的作用:不修改被装饰函数的功能外,再通过闭包的方式添加额外的功能!

  3.基本结构:    

复制代码
1 def outer_func(func):
2     def inner_func():
3         pass
4     return inner_func
5 
6 
7 @outer_func # test = outer_func(test)
8 def test():
9     pass
复制代码

  重点:上述代码的第七行和第八行是重点,看到这个语法糖要想到其本质: test = outer_func(test)

  4.结论:

    (1). 装饰前的test函数和闭包外层函数的func是一样的;

    (2). 装饰后的test函数是闭包内层函数的引用,也就是说此时test指向了inner_func函数体;

    (3). 装饰器一般不改变原先函数的行为。

  5.装饰器的一个小问题

    与其说是装饰器的问题,不如说是闭包的问题!

    一个函数被装饰之后,它的函数名会发生变化,变成了闭包的内层函数名。那该怎么解决这个问题呢?

    使用funtools.wraps()这个装饰器就可以完美解决这个问题了,因为这个装饰器会保留被装饰函数的一些基本信息。

    

复制代码
 1 import functools
 2 
 3 
 4 def outer_func(func):
 5     # 使用这个装饰器,可以保留被装饰函数的一些基本信息,如名称不变
 6     @functools.wraps(func)
 7     def inner_func(*args, **kwargs):
 8         func(*args, **kwargs)
 9 
10     # inner_func.__name__ = func.__name__
11     return inner_func
12 
13 
14 @outer_func
15 def test(*args, **kwargs):
16     print('%s 正在运行。。。。' % test.__name__)
17 
18 
19 test()
复制代码

 

 

三、装饰器内存图解

  1.一个装饰器装饰一个函数的内存图解:

  

 

  2.两个装饰器装饰一个函数的内存图解

    

 四、装饰器传参数

  1.结构:由三层函数构成的,即用一个函数把闭包给封装起来,这个函数必须带有参数!

      最外层函数(set_args)返回闭包的外层函数的引用;

      闭包的外层函数(outer_fun)还是返回内层函数的引用。

    

复制代码
1 def set_args(args):
2     def outer_fun(func):
3         def inner_fun(*args, **kwargs):
4             func(*args, **kwargs)
5         return inner_func
6     return outer_fun
复制代码

 

  2.运行流程:    

复制代码
1 @set_args('123')
2 def test():
3     print('test')
4 
5 test()
复制代码

    (1).先执行@右边的函数,即先执行set_args('123'),

    (2).执行完set_args()后返回outer_fun的引用,此时就是test = outer_fun(test)这个熟悉的语法了,

    (3).接下来就执行被装饰的函数了。

猜你喜欢

转载自blog.csdn.net/qq_41804164/article/details/80462011