python 装饰器(1)应用:函数执行时间统计,函数调用频率限制,函数调用日志

一.装饰器简介

装饰器:在不修改函数源代码的基础上,添加函数功能

被装饰器装饰的函数名即使没有被调用(因为有@xxx,会触发运行装饰器),(装饰器工厂函数)定义装饰器的代码已经运行了(最内部的那个函数并没有运行)(把被装饰的原函数引用赋值给了装饰器内部的那个函数名),当下边通过该函数名调用时,会调用到装饰器内部的那个函数()

装饰器常用场景:函数执行时间统计,函数调用频率限制,函数调用日志,函数缓存,性能测试

二.实例

2.1 记录时间

#!/usr/bin/python
import time

def outter(func):
	def inner(*args,**kwargs):
		start_time = time.time()
		re = func(args[0])
		end_time = time.time()
		spend_time = end_time - start_time
		return({'spend_time':spend_time,'result':re})
	return inner

@outter        #等价于:  test = outter(test)   此处没装饰器标志符没有带括号 与下面三层装饰器不同
def test(x):       # 等价于:outter(test)(x)
	time.sleep(5)
	return 'test'+str(x)

x = test(2)
print(x)

》》》{'spend_time': 5.004472970962524, 'result': 'test2'}

2.2频率限制

#!/usr/bin/python
import time,random

def func_param(*args_o,**kwargs_o):
    #10秒内只能请求5次,传参为func_param(10,5)
    def outter(func):
        history = []
        def inner(*args_i,**kwargs_i):
            nonlocal history
            nowtime = time.time()
            print(nowtime)
            notrun = 0
            if len(history) == args_o[1]:
                maxtime = nowtime - history[0]
                if maxtime < args_o[0]:
                    print('请求频率过高')
                    notrun =1
                history.pop(0)
                history.append(nowtime)
            else:
                history.append(nowtime)
            print('history:{}'.format(history))
            if notrun:
                return '请求频率过高'
            re = func(args_i[0])
            return '目标函数返回:{}'.format(re)
        return inner
    return outter

@func_param(10,5)    #等价于:xx = func_param(10,5)(xx)
def xx(x):           #等价于:func_param(10,5)(xx)(x)
    return '123'+str(x)

for i in range(15):
    w = random.uniform(0,4)
    time.sleep(w)
    xx(i)

》》》
C:\Python3\python.exe F:/work/project/Local_debug/test.py
1606405214.0630307
history:[1606405214.0630307]
1606405217.3594472
history:[1606405214.0630307, 1606405217.3594472]
1606405221.1596596
history:[1606405214.0630307, 1606405217.3594472, 1606405221.1596596]
1606405221.3468597
history:[1606405214.0630307, 1606405217.3594472, 1606405221.1596596, 1606405221.3468597]
1606405225.1884668
history:[1606405214.0630307, 1606405217.3594472, 1606405221.1596596, 1606405221.3468597, 1606405225.1884668]
1606405227.9352918
history:[1606405217.3594472, 1606405221.1596596, 1606405221.3468597, 1606405225.1884668, 1606405227.9352918]
1606405227.9508915
history:[1606405221.1596596, 1606405221.3468597, 1606405225.1884668, 1606405227.9352918, 1606405227.9508915]
1606405230.969111
请求频率过高
history:[1606405221.3468597, 1606405225.1884668, 1606405227.9352918, 1606405227.9508915, 1606405230.969111]
1606405233.252918
history:[1606405225.1884668, 1606405227.9352918, 1606405227.9508915, 1606405230.969111, 1606405233.252918]
1606405236.0575264
history:[1606405227.9352918, 1606405227.9508915, 1606405230.969111, 1606405233.252918, 1606405236.0575264]
1606405236.9099412
请求频率过高
history:[1606405227.9508915, 1606405230.969111, 1606405233.252918, 1606405236.0575264, 1606405236.9099412]
1606405240.8693566
history:[1606405230.969111, 1606405233.252918, 1606405236.0575264, 1606405236.9099412, 1606405240.8693566]
1606405244.0043757
history:[1606405233.252918, 1606405236.0575264, 1606405236.9099412, 1606405240.8693566, 1606405244.0043757]
1606405244.7999773
history:[1606405236.0575264, 1606405236.9099412, 1606405240.8693566, 1606405244.0043757, 1606405244.7999773]
1606405248.3735948
history:[1606405236.9099412, 1606405240.8693566, 1606405244.0043757, 1606405244.7999773, 1606405248.3735948]

Process finished with exit code 0

实际应用中需改进为线程安全

#!/usr/bin/python
import time,random
from threading import Thread,Lock

lock1 = Lock()
def func_param(*args_o,**kwargs_o):
    #10秒内只能请求5次,传参为func_param(10,5)
    def outter(func):
        print('outter run')
        history = []
        def inner(*args_i,**kwargs_i):
            nonlocal history
            nowtime = time.time()
            print(nowtime)
            lock1.acquire()
            notrun = 0
            if len(history) == args_o[1]:
                maxtime = nowtime - history[0]
                if maxtime < args_o[0]:
                    print('请求频率过高')
                    notrun = 1
                history.pop(0)
            history.append(nowtime)
            print('history:{}'.format(history))
            lock1.release()
            if notrun == 1:
                return '请求频率过高'
            re = func(args_i[0])
            return '目标函数返回:{}'.format(re)
        return inner
    return outter

@func_param(10,5)
def test(x):
    print('test:{}'.format(x))
    return '123'+str(x)

print(1234567890)

pool = []
for i in range(20):
    th = Thread(target=test,args=(i,))
    pool.append(th)

for th in  pool:
    w = random.randint(0,4)
    time.sleep(w)
    th.start()

for th in pool:
    th.join()

》》》》
outter run
1234567890
1606404622.2749765
history:[1606404622.2749765]
test:0
1606404626.2901838
history:[1606404622.2749765, 1606404626.2901838]
test:1
1606404627.3051856
history:[1606404622.2749765, 1606404626.2901838, 1606404627.3051856]
test:2
1606404630.3055935
history:[1606404622.2749765, 1606404626.2901838, 1606404627.3051856, 1606404630.3055935]
test:3
1606404632.3172083
history:[1606404622.2749765, 1606404626.2901838, 1606404627.3051856, 1606404630.3055935, 1606404632.3172083]
test:4
1606404633.3210242
history:[1606404626.2901838, 1606404627.3051856, 1606404630.3055935, 1606404632.3172083, 1606404633.3210242]
test:5
1606404634.3214262
请求频率过高
history:[1606404627.3051856, 1606404630.3055935, 1606404632.3172083, 1606404633.3210242, 1606404634.3214262]
1606404636.3358297
请求频率过高
history:[1606404630.3055935, 1606404632.3172083, 1606404633.3210242, 1606404634.3214262, 1606404636.3358297]
1606404638.341039
请求频率过高
history:[1606404632.3172083, 1606404633.3210242, 1606404634.3214262, 1606404636.3358297, 1606404638.341039]
1606404639.3550406
请求频率过高
history:[1606404633.3210242, 1606404634.3214262, 1606404636.3358297, 1606404638.341039, 1606404639.3550406]
1606404642.3678458
请求频率过高
history:[1606404634.3214262, 1606404636.3358297, 1606404638.341039, 1606404639.3550406, 1606404642.3678458]
1606404645.3720603
history:[1606404636.3358297, 1606404638.341039, 1606404639.3550406, 1606404642.3678458, 1606404645.3720603]
test:11
1606404646.3860621
history:[1606404638.341039, 1606404639.3550406, 1606404642.3678458, 1606404645.3720603, 1606404646.3860621]
1606404646.3860621
test:12
请求频率过高
history:[1606404639.3550406, 1606404642.3678458, 1606404645.3720603, 1606404646.3860621, 1606404646.3860621]
1606404649.3988674
history:[1606404642.3678458, 1606404645.3720603, 1606404646.3860621, 1606404646.3860621, 1606404649.3988674]1606404649.3988674

test:14请求频率过高

history:[1606404645.3720603, 1606404646.3860621, 1606404646.3860621, 1606404649.3988674, 1606404649.3988674]
1606404651.3998737
请求频率过高
history:[1606404646.3860621, 1606404646.3860621, 1606404649.3988674, 1606404649.3988674, 1606404651.3998737]
1606404654.4136794
请求频率过高
history:[1606404646.3860621, 1606404649.3988674, 1606404649.3988674, 1606404651.3998737, 1606404654.4136794]
1606404657.4155014
history:[1606404649.3988674, 1606404649.3988674, 1606404651.3998737, 1606404654.4136794, 1606404657.4155014]
test:18
1606404659.429905
history:[1606404649.3988674, 1606404651.3998737, 1606404654.4136794, 1606404657.4155014, 1606404659.429905]
test:19

Process finished with exit code 0

参考:

python装饰器的参数传递 - 贾祥飞 - 博客园

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值