python的裝飾器可用於權限校驗,週期性函數調用等功能,下面通過兩種方式實現週期性函數的調用。
# -*- coding:utf-8 -*-
from functools import wraps
import time
import datetime
_ts = lambda: time.time()
# 通過__call__實現裝飾器類
class PeriodLoopingCall:
def __init__(self, period=60, max_count=0):
self.period = period
self.count = max_count
def __call__(self, func):
@wraps(func)
def wrapper(*args, **kwargs):
while self.count > 0:
start_time = _ts()
func(*args, **kwargs)
self.count -= 1
end_time = _ts()
delay = end_time - start_time - self.period
time.sleep(-delay if delay < 0 else 0)
return wrapper
# 通過閉包實現裝飾器函數
# 由於使用了nonlocal,需要在python 3環境下運行
def period_exec_func(period=60, max_count=0):
def decorator(func):
#使用functools.wraps函數防止原始函數的屬性被裝飾器函數的屬性替換。
#即防止這裏的print_info函數屬性被wrapper函數屬性替換。
count = 0
@wraps(func)
def wrapper(*args, **kwargs):
nonlocal count
while count < max_count:
start_time = _ts()
func(*args, **kwargs)
count += 1
end_time = _ts()
delay = end_time - start_time - period
time.sleep(-delay if delay < 0 else 0)
return wrapper
return decorator
@period_exec_func(period=2, max_count=3)
def print_info1(info):
date = datetime.datetime.now().strftime('%Y-%m-%d %H:%M:%S')
info = "%s %s" %(date, info)
print(info)
@PeriodLoopingCall(period=2, max_count=3)
def print_info2(info):
date = datetime.datetime.now().strftime('%Y-%m-%d %H:%M:%S')
info = "%s %s" %(date, info)
print(info)
def main():
info1 = "This is period decorator function test"
print_info1(info1)
print("*"*60)
info2 = "This is period decorator class test"
print_info2(info2)
if __name__ == "__main__":
main()
運行結果:
2019-10-20 11:09:48 This is period decorator function test
2019-10-20 11:09:50 This is period decorator function test
2019-10-20 11:09:52 This is period decorator function test
************************************************************
2019-10-20 11:09:54 This is period decorator class test
2019-10-20 11:09:56 This is period decorator class test
2019-10-20 11:09:58 This is period decorator class test