• 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

  • 相关阅读:
    Oracle 系统表大全
    oracle高效分页存储过程(百万数据级)
    PowerDesigner中name与comment互相转换脚本
    一些web开发中常用的、做成cs文件的js代码
    Ado.net Entity Model 模板出错的修复
    做ssl通道时遇到“请求被中止: 未能创建 SSL/TLS 安全通道”问题的解决方法
    SQLSERVER 2008空间数据库学习(一)
    jquery的全选、全不选、反选例子
    win7 64位下使用oracle ado.net entity framework
    半角/全角互换的代码
  • 原文地址:https://www.cnblogs.com/sometingintheway/p/12727785.html
Copyright © 2020-2023  润新知