zoukankan      html  css  js  c++  java
  • python装饰器

    理解装饰器

    1.函数名

    函数名是函数的名字,本质:变量,特殊的变量。

    1)函数名存着函数的内存地址。

     内存地址:

    2)第一类对象(first-class object)

    1.可以在运行期间创建 2.可用作函数参数或返回值 3.可存入变量的实体。

    2.闭包

    1、 闭包函数 : 内部函数包含对外部作用域而非全局作用域变量的引用,该内部函数称为闭包函数

    2、闭包的作用:爬虫、装饰器

    当程序执行遇到函数执行时,会在内存空间开辟局部命名空间,当函数执行完毕,该命名空间会被销毁。但是如果这个函数内部形成闭包,则该内存空间不会随着函数执行完而消失。

    3、如何判断是否是闭包:print(函数名.__closure__) 结果是 cell 说明是闭包,结果是 None 说明不是闭包。

    如何判断它是否是一个闭包函数呢? 内层函数名.__closure__ cell 就是=闭包

    def wrapper():
        name = 'summer'
        
        def inner():
            print(name)                  #可以使用外部作用域,但不是全局作用域
        inner()
        print(inner.__closure__)
    
        
    wrapper()

    结果:

     3.装饰器

    3.1了解装饰器

    装饰器是可调用的对象。其参数是被装饰的函数。装饰器可能会处理当前函数。然后把它(函数变量)返回,或者将其替换成另一个函数或可调用对象。

    装饰器本质: 就是一个python函数,他可以让其他函数在不需要做任何代码变动的前提下,增加额外的功能,装饰器的返回值也是一个函数对象。

    
    
    import time
    def timmer(f):                           
        def inner():
            start_time = time.time()             
            f()                                                         
            end_time = time.time()             
            print('此函数的执行时间为{}'.format(end_time - start_time))         
        return inner                       
    def func1():                           
        print('in func1')               
        time.sleep(1)                    
    func1 = timmer(func1)               
    print(func1)
    func1()                           # 这里的func1是全新的func1,就是上面的赋值,此时相当于执行 inner函数
    输出结果:
    <function timmer.<locals>.inner at 0x03822DF8>
    in func1
    此函数的执行时间为1.0003533363342285
     

    语法糖: 想测试谁,前面加@装饰器函数,即可。 写装饰器,约定俗成,函数名为wrapper

    def wrapper(func):
        def inner(*args,**kwargs):
            '''被装饰函数之前'''
            ret = func(*args,**kwargs) # 被装饰的函数
            '''被装饰函数之后'''
            return ret
        return inner
    @wrapper
    def func(*args,**kwargs):
        print(args,kwargs)
        return 666
    print(func())
    输出结果:
    () {}
    666

    装饰器利用return制造了一个假象,func()执行,其实是执行inner() , func()把原来的func()给覆盖了。

    2。python何时执行装饰器

    import functools
    
    def dec(func):
        @functools.wraps(func)  # 加这句是为了防止装饰器对被装饰函数的影响
        def wrapper(*args, **kwargs):
            print('this is a wrapper')
            return func(*args, **kwargs)
    
        return wrapper
    
    
    @dec  # foo = dec(foo)
    def foo():
        print('foo() called')
    
    
    foo()
    # dec -> foo= dec(foo) ->return wrapper-> foo = wrapper() ->print('this is a wrapper') return foo() -> print('foo() called')

    首先说明@dec的含义,这可以看作是foo=dec(foo)的一种简写(这其实类似于数学中的函数复用),既然如此,那么在foo()前加上@dec相当于foo=wrapper。剩下的就是类似例3的过程了,首先执行装饰器内的打印语句,然后返回foo(),执行真实的foo()内容。实际上上述过程省略了一个重要的点,那就是装饰器函数在被装饰函数定义好后立即执行,这个如何理解呢,可以理解为当被装饰函数定义好后,即执行了foo=dec(foo)操作,因此实际上在例4中,可以将上例稍做修改,再去掉最后一行的foo()

    def dec(func):
        print('this is dec')
        @functools.wraps(func)            # 加这句是为了防止装饰器对被装饰函数的影响
        def wrapper(*args,**kwargs):
            print('this is a wrapper')
            return func(*args,**kwargs)
        return wrapper
        
    @dec
    def foo():
        print('foo() called')

    详细解释:https://blog.csdn.net/shahuzi/article/details/81254557

  • 相关阅读:
    【BZOJ4198】[Noi2015]荷马史诗 贪心+堆
    【BZOJ4200】[Noi2015]小园丁与老司机 DP+最小流
    【BZOJ2839】集合计数 组合数+容斥
    【BZOJ2989】数列 kd-tree
    【BZOJ4240】有趣的家庭菜园 树状数组+贪心
    【BZOJ4238】电压 DFS树
    【BZOJ4237】稻草人 cdq分治+单调栈+二分
    Python Web学习笔记之WebSocket原理说明
    Python Web学习笔记之Cookie,Session,Token区别
    Python Web学习笔记之图解TCP/IP协议和浅析算法
  • 原文地址:https://www.cnblogs.com/sometingintheway/p/12727785.html
Copyright © 2011-2022 走看看