• 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)即可;

    talk is cheap,show me the code
  • 相关阅读:
    线程 定时任务 实现思路
    Days Floating In ShenZhen(1)
    由于未能找到具有自动生成的控件来引发回发事件,导致发生错误
    在ASP.NET中使用AJAX.NET (转译自MSDN)(二)
    Every Time I Wake up I want sleep more
    漂泊在深圳的日子2
    512今日历程
    流金岁月
    对自己的思考
    关于绑定自动生成的下拉式菜单的错误
  • 原文地址:https://www.cnblogs.com/xuanxuanlove/p/9568177.html
Copyright © 2020-2023  润新知