<kbd id="afajh"><form id="afajh"></form></kbd>
<strong id="afajh"><dl id="afajh"></dl></strong>
    <del id="afajh"><form id="afajh"></form></del>
        1. <th id="afajh"><progress id="afajh"></progress></th>
          <b id="afajh"><abbr id="afajh"></abbr></b>
          <th id="afajh"><progress id="afajh"></progress></th>

          Python編寫(xiě)裝飾器,給任意函數(shù)計(jì)時(shí)

          共 1767字,需瀏覽 4分鐘

           ·

          2021-05-21 23:03

          在開(kāi)發(fā)代碼時(shí),經(jīng)常有這樣的需求,想知道調(diào)用一個(gè)函數(shù)的入?yún)?、返回值、花費(fèi)時(shí)間。


          對(duì)應(yīng)這個(gè)調(diào)用,我們可以自己在函數(shù)開(kāi)頭打印參數(shù)、末尾打印結(jié)果、結(jié)尾時(shí)間減去開(kāi)始時(shí)間計(jì)時(shí)。


          然而這樣的代碼,其實(shí)任何函數(shù)都一樣,有沒(méi)有辦法寫(xiě)一次代碼多次調(diào)用呢。


          這其實(shí)就是“給任何函數(shù),增加一個(gè)公共的附加特性”,可以用Python的解釋器解決。


          # 1、導(dǎo)入相關(guān)的包


          import functoolsimport loggingimport time
          log_format = "%(asctime)s %(message)s"logging.basicConfig(format=log_format, level=logging.INFO)


          這用到了functools包,它有wraps方法,是裝飾需要的函數(shù)。


          # 2、編寫(xiě)裝飾器


          def time_logger(func):  @functools.wraps(func)  def wrapper_timer(*args, **kwargs):    logging.info(f"BeginFunction {func.__name__!r}, args={args}, kwargs={kwargs}")    start_time = time.perf_counter()  # 1    value = func(*args, **kwargs)    end_time = time.perf_counter()  # 2    run_time = end_time - start_time  # 3    logging.info(f"EndFunction {func.__name__!r} in {run_time:.4f} secs")    return value
          return wrapper_timer


          大家注意,這個(gè)裝飾器會(huì)被任何函數(shù)使用。其中的func(*args, **kwargs)中的func就是目標(biāo)函數(shù),args、kwargs是這個(gè)函數(shù)調(diào)用的參數(shù)。


          這就實(shí)現(xiàn)了一個(gè)裝飾器。


          # 3、使用裝飾器給函數(shù)計(jì)時(shí)


          @time_loggerdef my_func(name, age):  logging.info(f"my func begin, {name}, {age}")  time.sleep(2)  logging.info(f"my func end, {name}, {age}")


          @time_logger就是計(jì)時(shí)器的裝飾器使用方式,任何函數(shù)只需要這個(gè)簡(jiǎn)單地一行代碼,就可以加上這個(gè)功能。


          # 4、我們來(lái)看看調(diào)用效果


          執(zhí)行如下代碼:

          my_func("antpython", "99")


          打印結(jié)果為:

          2021-05-17 20:30:26,294 BeginFunction 'my_func', args=('antpython', '99'), kwargs={}2021-05-17 20:30:26,294 my func begin, antpython, 992021-05-17 20:30:28,295 my func end, antpython, 992021-05-17 20:30:28,295 EndFunction 'my_func' in 2.0007 secs


          其中第一行BeginFunction、最后一行EndFunction,都是裝飾器里面的輸出。


          而my func begin、my func end,則是自己的函數(shù)的輸出。


          # 5、最后的總結(jié)


          對(duì)于裝飾器,可以有很多用途:

          • WEB服務(wù)中檢測(cè)用戶(hù)是否登錄

          • 加入所有函數(shù)的日志、計(jì)時(shí)功能

          • 對(duì)所有訪問(wèn)數(shù)據(jù)庫(kù)的函數(shù)加上入侵檢測(cè)功能

          • 對(duì)用戶(hù)的訪問(wèn)請(qǐng)求做攻擊檢測(cè)

          • 自動(dòng)處理數(shù)據(jù)庫(kù)的鏈接提取、提交、回滾等操作


          只要是一個(gè)通用的功能,都可以用裝飾器來(lái)解決。這在其他語(yǔ)言比如JAVA中也叫做攔截器、代理等功能。


          這是一個(gè)很有用的特性,趕快試試吧!

          瀏覽 106
          點(diǎn)贊
          評(píng)論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報(bào)
          評(píng)論
          圖片
          表情
          推薦
          點(diǎn)贊
          評(píng)論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報(bào)
          <kbd id="afajh"><form id="afajh"></form></kbd>
          <strong id="afajh"><dl id="afajh"></dl></strong>
            <del id="afajh"><form id="afajh"></form></del>
                1. <th id="afajh"><progress id="afajh"></progress></th>
                  <b id="afajh"><abbr id="afajh"></abbr></b>
                  <th id="afajh"><progress id="afajh"></progress></th>
                  久久久久亚洲AV成人网址老师板 | 亚洲黄色片 | 伊人成人中文字 | 国产精品在线观看 | 免费看A片18 的视频 |