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

 

posted @ 2020-09-06 21:34  L1m1t  阅读(106)  评论(0编辑  收藏  举报