python 学习笔记 day12 装饰器进阶

装饰器的原则:

开放封闭原则:对扩展是开放的,对修改是封闭的;

装饰器的作用:

在不改变原函数调用的情况下,扩展被装饰函数的功能(可以在装饰器函数内部,在被装饰函数的前后分别添加相应的功能);

装饰器函数的本质:

装饰器函数本质上就是一个闭包函数;

装饰器函数固定模式:

def wrapper(f): #装饰器函数
    def inner(*args):
        print("在被装饰的函数之前添加的功能")  #1最先被打印
        ret=f(*args) #被装饰的函数func带有返回值
        print("在被装饰的函数之后添加的功能")  #3 被打印
        return ret
    return inner

@wrapper
def func(a,b,c): #被装饰的函数
    print(a,b,c)  #2.执行被装饰的函数时被打印
    return "哈哈哈哈"  #4.最后返回的结果在全局中被打印

ret=func(1,2,3)
print(ret)

 

wraps

先介绍一个函数的功能,就是可以以一个字符串的形式返回一个函数的函数名 func.__name__ ;

可以返回函数的注释信息,就是写在函数内部功能之前 最开始的注释 func.__doc__;

def func():
    '''我是一个func函数'''
    print('hello')
print(func.__name__,type(func.__name__)) #以字符串的形式返回函数的名
print(func.__doc__)  #返回一个函数内部注释

运行结果:

现在我们来看装饰器固定模式这个代码,有一个很有意思的事:

def wrapper(f): #装饰器函数
    def inner(*args):
        print("在被装饰的函数之前执行的代码")
        ret=f()
        print("在被装饰的函数之后执行的代码")
        return ret
    return inner  #wrapper()函数有返回值

@wrapper
def func(a,b,c):
    print(a,b,c)
    return "哈哈哈哈"
print(func.__name__) 

 运行结果:

我们打印func()函数的名字(使用func.__name__ 以字符串的形式打印函数名)发现竟然是inner!

原因是,我们在被装饰的函数func 定义上方写了@wrapper,相当于在函数定义结束后写了 func=wrapper(func)  其实你会发现,我们之前跟wrapper()函数同一级别定义的func()函数已经以一个参数的形式传给了f

,然后wrapper()函数的返回值inner(其实也是一个函数,只不过在wrapper()函数内部的一个闭包函数)我们给了变量func,所以这里的func 不再是原来在全局空间定义的函数了,而是一个inner函数名,那我们怎么才可以跟之前一样,func.__name__时打印出func的函数名呢,也就是调用func()时在扩充了功能的前提下,就跟真实的调用原来定义的那个函数一样呢?

我们可以这样操作:

from functools import wraps
def wrapper(f):
    @wraps(f)
    def inner(*args):
        print("在被装饰的函数之前执行的代码")
        ret=f(*args)
        print("在被装饰的函数之后执行的代码")
        return ret
    return inner

@wrapper
def func(a,b):
    print(a,b)
    return "哈哈哈哈"
print(func.__name__)
print(func(1,2))

 也就是from functools import wraps导入wraps ,然后在装饰器函数的内部,inner()闭包函数的上方加上 @wraps(f)即可;

猜你喜欢

转载自www.cnblogs.com/xuanxuanlove/p/9568177.html
今日推荐