美文网首页
Python装饰器的简单理解

Python装饰器的简单理解

作者: AndroidKy | 来源:发表于2019-12-15 11:58 被阅读0次

    没别的意思,稍微记录一下Python装饰器的简单理解

    对Python语法尤其是对函数式编程不太熟悉的话可能理解Python的装饰器模式会比较费劲一点,这边简单理解一下Python中的装饰器是个什么东西。

    首先,很重要的一点就是Python可以把函数当作对象引用一样传递,所以我们可以把函数当作参数传递给另一个函数,也可以把函数当作另一个函数的返回值,是不是感觉要上天?

    加上()的话表示函数在这句代码执行的时候就调用了,不加则表示仅仅当作一个引用传递,并不调用

    def func_a(func_r1, func_r2):
        print func_r1()
        return func_r2
    
    
    def func_b():
        return "hi,kyson.I am func b"
    
    
    def func_c():
        return "hi,kyson.I am func c"
    
    
    if __name__ == '__main__':
        print func_a(func_b, func_c)()
    

    一开始看到上面这段的时候其实并没有多少感觉,但是我们只要稍微深究一下就会发现这里面其实可以做很多事情了。

    我们可以想一个例子,比如:我现在想要设计一个函数,这个函数可以把其他函数的调用时间打印下来,我们把这个函数暂时命名为:time_cost。

    用刚才的想法,我们只需要把任意函数当作参数传到time_cost,然后time_cost调用外部传进来的函数之前和之后计算一下时间,然后打印即可:

    def time_cost2(func_r):
        start = time.clock()
        func_r()
        end = time.clock()
        print "cost: %.4f" % (end - start)
    

    这样,我们就可以调用time_cost2函数,并传入真正想要调用的函数,就可以执行函数并打印执行消耗的时间了,cool~

    到这里其实装饰器已经完成了,但是还不够。因为每次我们想调用函数的时候只能当作参数传给time_cost2,然后执行time_cost2,这样如果有很多函数需要调用,岂不是每次调用都要换成time_cost2?

    这时候Python又露出了蜜汁笑容:不好意思,在我这儿函数名可以赋值给变量

    那又怎样?

    那就可以把time_cost2函数名称赋值给以真正的函数名称为变量名的变量了!(不好意思,其实很简单的一句话我解释不好)

    看看代码吧,就容易理解了:

    def time_cost2(func_r):
        start = time.clock()
        func_r()
        end = time.clock()
        print "cost: %.4f" % (end - start)
    
    
    def func2():
        time.sleep(3)
    
    
    func2 = time_cost2(func2)
    
    if __name__ == '__main__':
        func2()
    

    我在执行func2()的时候你猜怎么着?报错了!

    Traceback (most recent call last):
      File "D:/Dev/Python/Workspace/test/test.py", line 49, in <module>
        func2()
    TypeError: 'NoneType' object is not callable
    

    会过来看看代码,原来func2在赋值的时候已经是time_cost2(func2)执行了的,所以func2就是time_cost2(func2)的返回值,而并不是可调用的函数,尴尬。

    所以问题就变成了,我怎么样让time_cost2(func2)暂时先不执行,当作可调用的函数赋值给func2?

    这时候文章开头提到的一点就很重要了:函数可以当作另一个函数的返回值。

    所以这时候代码变成了这样:

    def time_cost(func1):
        def time_cost_wrap():
            start = time.clock()
            func1()
            end = time.clock()
            print "cost: %.4f" % (end - start)
    
        return time_cost_wrap
    
    
    def func():
        time.sleep(3)
    
    
    func = time_cost(func)
    
    if __name__ == '__main__':
        func()
    

    time_cost函数里面定义了time_cost_wrap函数,这个函数做的事情就是刚才time_cost函数做的事情,然后time_cost返回了time_cost_wrap函数,这里注意是返回的函数名称,并没有执行time_cost_wrap,所以当我们把time_cost(func)赋值给func变量的时候,实际上我们是把time_cost_wrap函数赋值给了func,这时候我们再执行func()的时候就相当于执行了time_cost_wrap()。

    Perfect.

    完成代码:

    # -*- coding:utf-8 -*-
    import time
    
    
    def func_a(func_r1, func_r2):
        print func_r1()
        return func_r2
    
    
    def func_b():
        return "hi,kyson.I am func b"
    
    
    def func_c():
        return "hi,kyson.I am func c"
    
    
    def time_cost2(func_r):
        start = time.clock()
        func_r()
        end = time.clock()
        print "cost: %.4f" % (end - start)
    
    
    def func2():
        time.sleep(3)
    
    
    func2 = time_cost2(func2)
    
    
    def time_cost(func1):
        def time_cost_wrap():
            start = time.clock()
            func1()
            end = time.clock()
            print "cost: %.4f" % (end - start)
    
        return time_cost_wrap
    
    
    def func():
        time.sleep(3)
    
    
    func = time_cost(func)
    
    if __name__ == '__main__':
        # print func_a(func_b,func_c)
        # func2()
        func()
    

    相关文章

      网友评论

          本文标题:Python装饰器的简单理解

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