Decorator(装饰器) 是 Python 中很好用的一个东西,只要 @
一下就可以处理掉很多东西,其实 Decorator(装饰器) 不难理解,而且容易使用所以在 Python 中很常使用到。不过这篇没有要讲太深,只是让你比较容易理解与使用而已。
那麽这麽好用的东西怎麽使用呢?就让我们自己做一个简单的出来吧!就先来刻个计算程序执行时间的装饰器好了,这样可以更快的了解。首先架构为这样(就一个资料夹里面有个档案而已啦,算不上架构):
decorator_test/
└── test.py
档案内容为:
test.py
from time import time
def time_counter(func):
def wrapper(*args, **kwargs): # 习惯上会取名叫 wrapper
start = time()
result = func(*args, **kwargs)
end = time()
usage_time = (end - start)
return result, usage_time
return wrapper
# 不要括号喔
@time_counter
def star_triangle(times):
step = ""
for i in range(1, times+1, 2):
for j in range((times-i)//2):
step += " "
for j in range(i):
step += "*"
step += "\n"
return step
res = star_triangle(5000) # 5000 如果跑太久可以适当的减少它
print("Time: {:>30.24f} second".format(res[1]))
执行後的时间大概会长这样(嗯,我没有让它输出,不然很恐怖)
> Time: 3.177063703536987304687500 second
蛤,这样就一个喔,啊它到底是怎样出现的?
别急,把15行删掉(@time_counter
那行),再把27行改成这样
res = time_counter(star_triangle)(5000) # 5000 如果跑太久可以适当的减少它
应该会出现类似的结果(秒数不一样很正常)
> Time: 3.209057331085205078125000 second
这样懂了吗?还记的 Day 06 讲过的这些吗?
在 Python 中,Function 的地位和 C++、Java等不同,是属於 "First-class Citizen" (一等公民),故称作 "First-class function" (一级函数)。
什麽是 "First-class Citizen" 呢?跟二等公民又差在哪呢?
最明显的差别是 Python 中的 Function 可以当成参数传递并执行(对啦,我就是只想讲这句而已,其他暂时不太重要)。
Decorator(装饰器) 就是把@
下面的 Function 当成参数传递并执行了,大概就是每次呼叫 Function 都会像这样一层一层转换(这边只是方便理解而已):
Step1: res = star_triangle(5000)
Step2: res = time_counter(star_triangle)(5000)
Step3: res = wrapper(5000):
Step4: res get wrapper return
因为 func
这个东西位於 time_counter
的里面,所以同样位於time_counter
里面的 wrapper
不需要把它当参数也可以使用(大概就是台中市民搭公车免费,你住在北区的话,你也可以免费的意思)
啊如果装饰器想要有参数的话怎麽办,就再加一层变这样
test.py
from time import time
def time_counter(func):
def wrapper(*args, **kwargs): # 习惯上会取名叫 wrapper
start = time()
result = func(*args, **kwargs)
end = time()
usage_time = (end - start)
return result, usage_time
return wrapper
def record_now_time(time_format="%Y-%m-%d %H:%M:%S"):
def decorator(func):
def wrapper(*args, **kwargs):
print(datetime.now().strftime(time_format) + " - Start function: " + func.__name__)
# __name__ 可以取得 Function 的名称
result = func(*args, **kwargs)
print(datetime.now().strftime(time_format) + " - End function: " + func.__name__)
return result
return wrapper
return decorator
@record_now_time(time_format="%H:%M:%S")
def star_triangle(times):
step = ""
for i in range(1, times+1, 2):
for j in range((times-i)//2):
step += " "
for j in range(i):
step += "*"
step += "\n"
return step
res = star_triangle(5000) # 5000 如果跑太久可以适当的减少它
这样执行的输出会变这样(最後面的print
要删掉)
> 22:20:26 - Start function: star_triangle
> 22:20:29 - End function: star_triangle
如果想要同时使用多个装饰器怎麽办,就加上去啊,会变成这样:
test.py
from time import time
def time_counter(func):
def wrapper(*args, **kwargs): # 习惯上会取名叫 wrapper
start = time()
result = func(*args, **kwargs)
end = time()
usage_time = (end - start)
return result, usage_time
return wrapper
def record_now_time(time_format="%Y-%m-%d %H:%M:%S"):
def decorator(func):
def wrapper(*args, **kwargs):
print(datetime.now().strftime(time_format) + " - Start function: " + func.__name__)
result = func(*args, **kwargs)
print(datetime.now().strftime(time_format) + " - End function: " + func.__name__)
return result
return wrapper
return decorator
@time_counter
@record_now_time(time_format="%H:%M:%S")
def star_triangle(times):
step = ""
for i in range(1, times+1, 2):
for j in range((times-i)//2):
step += " "
for j in range(i):
step += "*"
step += "\n"
return step
res = star_triangle(5000) # 5000 如果跑太久可以适当的减少它
print("Time: {:>30.24f} second".format(res[1]))
然後它就会一层一层吃上去,类似这样:
Step1: res = star_triangle(5000)
Step2: res = record_now_time(time_format="%H:%M:%S")(star_triangle)(5000)
Step3: res = time_counter()(record_now_time)(time_format="%H:%M:%S")(star_triangle)(5000)
Step4: res = wrapper(5000):
Step5: res get wrapper return
有没有发现到後面越来越长了,写个装饰器更加的简单明了对吧!
Python进阶技巧 (3) — 神奇又美好的 Decorator ,嗷呜!
那麽就大概这样,这篇是让你在使用套件时,遇到装饰器不会不知如何使用而已。话说其实不只 Funciton 可以变成装饰器,Class 也可以。不过关於这个问题,我不会在下个文章讲解(这是一个小坑了,真要讲大概又要开几篇来讲,话说都第五天了还没进主题)。
大家掰~掰~
Git与Github关系? 说明 : Github是Git进行版本控制软件的服务平台供应商之一。 G...
上一次我们完成了 ContextMenu 的部分,ContextMenu 也有了属於自己的 View...
「一般来说,如果你所依赖的模组包含了超过你所需要的,那就是有害的,这可能导致不必要的重新编译和重新...
一山还有一山高课程难度有增无减的一周 上周老师说只要学完抽象类别後应该没有更难的东西,谁知道!!这周...
我们将从价格、曲库、音质、歌词方面比较 Spotify 和 Apple Music,让你可以一次了解...