Python實(shí)現(xiàn)屬性可修改的裝飾器方式
如何實(shí)現(xiàn)屬性可修改的函數(shù)裝飾器
實(shí)際案例
為分析程序內(nèi)哪些函數(shù)執(zhí)行時(shí)間開銷比較大,
我們定義一個(gè)帶timeout參數(shù)的函數(shù)裝飾器,timeout是一個(gè)時(shí)間閥值
比如運(yùn)行時(shí)間超過1秒的都是比較慢的,這種函數(shù)比較可疑。
裝飾器功能如下:
- 統(tǒng)計(jì)被裝飾函數(shù)單詞調(diào)用運(yùn)行時(shí)間;
- 時(shí)間大于參數(shù)timeout的,將此次函數(shù)調(diào)用記錄到log日志中;
- 運(yùn)行時(shí)可修改timeout的值(可以動(dòng)態(tài)修改timeout)。
解決方案
為包裹函數(shù)增加一個(gè)函數(shù)作為包裹函數(shù)的屬性,用來修改閉包中使用的自由變量。
在python3中:使用nonlocal訪問嵌套作用域中的變量引用。
代碼演示
# _*_ encoding:utf-8 _*_
from functools import wraps
from random import randint
import time
import logging
# 內(nèi)部統(tǒng)計(jì)一個(gè)算法的運(yùn)行時(shí)間
def warn(timeout):
""" 帶參數(shù)裝飾器也就是內(nèi)部能返回一個(gè)裝飾器 """
# python2中因?yàn)闆]有nonlocal,可以將timeout聲明為可變對象
# timeout = [timeout]
# 裝飾器冬季func運(yùn)行時(shí)間
def decorator(func):
# 定義包裹函數(shù)
def wrapper(*args, **kwargs):
start = time.time()
res = func(*args, **kwargs)
# 得到運(yùn)行時(shí)間
used = time.time() - start
if used > timeout:
msg = '"%s": %s > %s' % (func.__name__, used, timeout)
# 如果超時(shí)輸入到日志當(dāng)中
logging.warning(msg)
# if used > timeout[0]:
# msg = '"%s": %s > %s' % (func.__name__, used, timeout[0])
# logging.warn(msg)
# return res
# 動(dòng)態(tài)修改函數(shù)屬性timeout值
def set_timeout(k):
# python3聲明嵌套作用域下變量,類似于global
nonlocal timeout
timeout = k
# python2中使用可變對象修改timeout
# timeout[0] = k
# 將set_timeout函數(shù)作為wrapper屬性,未來用戶就可以通過函數(shù)來調(diào)用到它。
wrapper.set_timeout = set_timeout
return wrapper
return decorator
# 測試代碼
@warn(1.5)
def test():
print('In test')
# 隨機(jī)進(jìn)入睡眠狀態(tài),百分之50概率
while randint(0, 1):
time.sleep(0.5)
for _ in range(30):
test()
# 測試運(yùn)行時(shí)修改timeout屬性等于1
test.set_timeout(1)
for _ in range(30):
test()
'''
運(yùn)行完前30個(gè)test函數(shù)后修改timeout=1。
運(yùn)行時(shí)可以看到timeout從1.5變成了1,如下:
WARNING:root:"test": 1.509084939956665 > 1.5
WARNING:root:"test": 1.004662036895752 > 1
'''總結(jié)
以上為個(gè)人經(jīng)驗(yàn),希望能給大家一個(gè)參考,也希望大家多多支持腳本之家。
相關(guān)文章
查找python項(xiàng)目依賴并生成requirements.txt的方法
今天小編就為大家分享一篇查找python項(xiàng)目依賴并生成requirements.txt的方法,具有很好的參考價(jià)值,希望對大家有所幫助。一起跟隨小編過來看看吧2018-07-07
Python使用DrissionPage實(shí)現(xiàn)數(shù)據(jù)分析工具
在短視頻時(shí)代,抖音數(shù)據(jù)蘊(yùn)含著巨大價(jià)值,本文我們將使用新興的DrissionPage替代Selenium,結(jié)合精心設(shè)計(jì)的UI框架,打造了一款顏值與實(shí)力并存的分析利器,感興趣的小伙伴可以了解下2025-05-05
淺談keras中的batch_dot,dot方法和TensorFlow的matmul
這篇文章主要介紹了淺談keras中的batch_dot,dot方法和TensorFlow的matmul,具有很好的參考價(jià)值,希望對大家有所幫助。一起跟隨小編過來看看吧2020-06-06
利用Tkinter和matplotlib兩種方式畫餅狀圖的實(shí)例
下面小編就為大家?guī)硪黄肨kinter和matplotlib兩種方式畫餅狀圖的實(shí)例。小編覺得挺不錯(cuò)的,現(xiàn)在就分享給大家,也給大家做個(gè)參考。一起跟隨小編過來看看吧,希望對大家有所幫助2017-11-11
Python OpenCV處理圖像之圖像像素點(diǎn)操作
這篇文章主要為大家詳細(xì)介紹了Python OpenCV處理圖像之圖像像素點(diǎn)操作,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2018-07-07
使用Python和PySpark進(jìn)行數(shù)據(jù)分析的實(shí)戰(zhàn)教程
數(shù)據(jù)分析是當(dāng)今信息時(shí)代中至關(guān)重要的技能之一,Python和PySpark作為強(qiáng)大的工具,提供了豐富的庫和功能,使得數(shù)據(jù)分析變得更加高效和靈活,在這篇文章中,我們將深入探討如何使用Python和PySpark進(jìn)行數(shù)據(jù)分析,需要的朋友可以參考下2024-01-01

