【第十八天】装饰器

作者: 人生苦短_我用Python | 来源:发表于2018-03-30 15:20 被阅读12次

    7.3

    1.装饰器

    装饰器(decorator)是一种高级py语法,装饰器可以对一个函数,方法或者类进行加工
    在py中,我们有多种方法对函数和类进行加工,装饰器从操作上入手
    为函数增加额外的指令,py最初没有装饰器这一语法
    装饰器在py2.5中才出现,最初只用于函数
    在py2.6以及之后的py版本中,装饰器被进一步用于类

    我们先定义两个简单的数学函数,一个用来计算平方和
    一个用来计算平方差:

    #获得平方和
    def square_sum(a,b):
        return a**2 + b**2  
    
    #获得平方差
    def square_diff(a,b):
        return a**2 - b**2
        
    if __name__ == '__main__':
        print(square_sum(3,4))    #打印25
        print(square_diff(3,4))   #打印-7
    

    在拥有了基本的数学功能之后,我们可能想为函数增加其他的功能
    比如打印输入,我们可以改写函数来实现这一点:

    #装饰:打印输入
    
    def square_sum(a,b):
        print('input:',a,b)
        return a**2 + b**2
    
    def square_diff(a,b):
        print('input:',a,b)
        return a**2 - b**2
        
    if __name__ == '__main__':
        print(square_sum(3,4))
        print(square_diff(3,4))
    

    我们修改了函数定义,为函数增加了功能,从代码中可以看到
    这两个函数在功能上的拓展有很高的相似性
    都是增加了print('input:',a,b)这一打印功能
    我们可以改用装饰器,定义功能拓展本身
    再把装饰器用于两个函数:

    def decorator_demo(old_function):
        def new_function(a,b):
            print('input',a,b)    #额外打印操作
            return old_function(a,b)
        return new_function
    
    @decorator_demo
    def square_sum(a,b):
        return a**2 + b**2
        
    @decorator_demo
    def square_diff(a,b):
        return a**2 - b**2
    
    if __name__ == '__main__':
        print(square_sum(3,4))
        print(square_diff(3,4))
    

    装饰器可以用def的形式定义,如上面代码中的decorator_demo()
    装饰器接受一个可调用的对象作为输入参数,并返回一个新的可调用对象
    装饰器新建了一个函数对象,也就是上面的new_function()
    在new_function()中,我们增加了打印的功能
    并通过调用old_function(a,b)来保留原有函数的功能

    定义好装饰器后,我们就可以通过@语法使用了
    在函数square_sum()和square_diff()定义之前
    调用@decorator_demo,实际上是将square_sum()
    或square_diff()传递给了decorator_demo()
    并将decorator_demo()返回的新的函数对象赋给原来的函数名
    square_sum()和square_diff()
    所以当我们调用square_sum(3,4)的时候,实际上发生的是:

    square_sum = decorator_demo(square_sum)
    square_sum(3,4)
    

    我们知道,py中的变量名和对象是分离的
    变量名其实是指向一个对象的引用
    从本质上,装饰器起到的作用就是名称绑定(name binding)
    让同一个变量名指向一个新返回的函数对象,从而达到修改函数对象的目的
    只不过,我们很少彻底更改函数对象,在使用装饰器时
    我们往往会在新函数内部调用旧的函数,以便保留旧函数功能

    下面看一个更有实用功能的装饰器,我们可以利用time包来测量程序运行的时间
    把测量程序运行时间的功能做成一个装饰器,将这个装饰器运用于其他函数
    将显示函数的实际运行时间:

    import time
    
    def decorator_timer(old_function):
        def new_function(*arg,**dict_arg):
            t1 = time.time()
            result = old_function(*arg,**dict_arg)
            t2 = time.time()
            print('time:',t2 - t1)
            return result
        return new_function
    @decorator_timer
    def sum(a,b):
        c = a + b
        return c
    if __name__ == '__main__':
        print(sum(3,4))
    
    time: 1.1920928955078125e-06
    7
    

    在new_function()中,除调用旧函数外
    还前后额外调用了一次time.time(),由于time.time()返回挂钟时间
    它们的差值反映了旧函数的运行时间,此外,我们通过打包参数的方法
    可以在新函数和旧函数之间传递所有的参数

    装饰器可以实现代码的可复用性,我们可以用同一个装饰器修饰多个函数
    以便实现相同的附加功能,比如说,在建设网站服务器时,我们能用不同函数
    表示对不同HTTP请求的处理,当我们每次处理HTTP请求前
    都想附加一个客户验证功能时,那么就可以定义一个统一的装饰器
    作用于每一个处理函数,这样,程序能重复利用,可读性也大为提高

    Python中的函数的参数定义和可变参数
    https://www.cnblogs.com/tqsummer/archive/2011/01/25/1944416.html

    相关文章

      网友评论

        本文标题:【第十八天】装饰器

        本文链接:https://www.haomeiwen.com/subject/ouricftx.html