python核心编程——装饰器
Posted tom-blogs
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了python核心编程——装饰器相关的知识,希望对你有一定的参考价值。
定义两个功能函数:
# -*- coding:utf-8 -*- def foo(): # 打印"foo..." print("foo...") def bar(): # 打印"bar..." print("bar...") foo() # foo... bar() # bar...
计算函数的运行时间,我们可以把函数改写为:
import time # 放在(文档)最顶端 def foo(): start = time.time() # 函数运行之前的时刻 print("foo...") time.sleep(1) # 因为该程序运行时间太短,所以运用time.sleep()延长1s时间 end = time.time() # 函数运行完后的时刻 print(end - start) # 打印运行的时间 def bar(): start = time.time() # 函数运行之前的时刻 print("bar...") time.sleep(1) # 因为该程序运行时间太短,所以运用time.sleep()延长1s时间 end = time.time() # 函数运行完后的时刻 print(end - start) # 打印运行的时间 foo() # foo... # 1.0006506443023682 bar() # bar... # 1.0007519721984863
通过在每个功能函数内部添加一些计算时间的代码,就能实现我们的需求,但是又出现了以下问题:
1、修改了功能函数本身(每次调用函数,都会打印运行的时间,如果有的时候,我不想打印呢?)。
2、代码量大,且重复(此处只有2个功能函数,我们可手动修改,如果有几十个,几百个,那岂不是要改到天手抽筋)。
所以,针对以上两点情况,及解决代码重复和不修改函数本身,我们可以新定义一个计算时间的函数:
import time def foo(): # 打印"foo..." print("foo...") def bar(): # 打印"bar..." print("bar...") def caltime(func): # 计算函数运行的时间 start = time.time() # 函数运行之前的时刻 func() time.sleep(1) # 因为该程序运行时间太短,所以运用time.sleep()延长1s时间 end = time.time() # 函数运行完后的时刻 print(end - start) caltime(foo) # foo... # 1.0009233951568604 caltime(bar) # bar... # 1.0008749961853027
我们发现,通过新建一个函数来实现一个功能,很方便、简洁。但是这样,函数的调用方式却发生了改变,比如:
我们最开始调用功能函数是:foo() 。现在要计算函数运行时间,我们的调用方式是:caltime(foo) 。
我们需要达到的需求是:就最终执行foo(),就可实现该函数本身的功能和计算该函数运行的时间。而不是caltime(foo)。
如果我们的项目中调用了几十次foo函数,并且都需要计算时间,那我们岂不是也要挨个把foo()改成caltime(foo) ,其实这也是一件恼火的事情。所以我们得像个办法(就是还是书写foo()调用函数,但是同时可以计算运行的时间):
import time def foo(): # 打印"foo..." print("foo...") def bar(): # 打印"bar..." print("bar...") def caltime(func): def inner(): start = time.time() func() time.sleep(1) end = time.time() print(end - start) return inner foo = caltime(foo) foo() # foo... # 1.0006935596466064
最后我们就是通过foo()而不是caltime(foo)来调用函数的。所以,我们就可通过把函数当作返回值传递,来实现最终的调用方式(调用函数时的书写方式)相同。
caltime(foo)的执行结果是,返回的inner函数(并不会执行inner函数),然后把这个inner函数赋值给foo(即foo=caltime(foo))。所以,foo()就相当于在执行inner()。
这里的caltime()就是装饰器,但是我们会发现,每次执行foo()之前,都会写上foo=caltime(foo),也挺麻烦的,所以装饰器更专业更优雅写法就是:
1、把装饰器caltime()写在功能函数前面;
2、把foo=caltime(foo)这句每次调用都会写(重复)的代码写成 @caltime 的方式,放到功能函数前面。
import time def caltime(func): def inner(): start = time.time() func() time.sleep(1) end = time.time() print(end - start) return inner @caltime # 此时caltime就相当于是foo=caltime(foo) def foo(): # 打印"foo..." print("foo...") def bar(): # 打印"bar..." print("bar...") # foo = caltime(foo) foo() # foo... # 1.000216007232666
以上是关于python核心编程——装饰器的主要内容,如果未能解决你的问题,请参考以下文章