91超碰碰碰碰久久久久久综合_超碰av人澡人澡人澡人澡人掠_国产黄大片在线观看画质优化_txt小说免费全本

溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務條款》

Python中Decorator的作用是什么

發布時間:2021-07-10 15:59:40 來源:億速云 閱讀:178 作者:Leah 欄目:編程語言

本篇文章給大家分享的是有關Python中Decorator的作用是什么,小編覺得挺實用的,因此分享給大家學習,希望大家閱讀完這篇文章后可以有所收獲,話不多說,跟著小編一起來看看吧。

首先來看一個簡單的例子:

# -*- coding: utf-8 -*-  def log_cost_time(func):      def wrapped(*args, **kwargs):          import time          begin = time.time()          try:              return func(*args, **kwargs)          finally:              print 'func %s cost %s' % (func.__name__, time.time() - begin)      return wrapped     @log_cost_time  def complex_func(num):      ret = 0      for i in xrange(num):          ret += i * i      return ret  #complex_func = log_cost_time(complex_func)     if __name__ == '__main__':      print complex_func(100000)     code snippet 0

代碼中,函數log_cost_time就是一個裝飾器,其作用也很簡單,打印被裝飾函數運行時間。

裝飾器的語法如下:

@dec  def func():pass

本質上等同于: func = dec(func)。

在上面的代碼(code snippet  0)中,把line12注釋掉,然后把line18的注釋去掉,是一樣的效果。另外staticmethod和classmethod是兩個我們經常在代碼中用到的裝飾器,如果對pyc反編譯,得到的代碼一般也都是  func = staticmthod(func)這種模式。當然,@符號的形式更受歡迎些,至少可以少拼寫一次函數名。

裝飾器是可以嵌套的,如

@dec0  @dec1  def func():pass

等將于 func = dec0(dec1(fun))。

裝飾器也有“副作用“”,對于被log_cost_time裝飾的complex_calc,  我們查看一下complex_func.__name__,輸出是:”wrapped“”。額,這個是log_cost_time里面inner  function(wrapped)的名字,調用者當然希望輸出是”complex_func”,為了解決這個問題,python提供了兩個函數。

  • functools.update_wrapper

原型: functools.update_wrapper(wrapper, wrapped[, assigned][, updated])

第三個參數,將wrapped的值直接復制給wrapper,默認為(__doc__, __name__, __module__)

第四個參數,update,默認為(__dict__)

  • unctools.wraps: update_wrapper的封裝

This is a convenience function for invoking  partial(update_wrapper,wrapped=wrapped,assigned=assigned,updated=updated) as a  function decorator when defining a wrapper function.

簡單改改代碼:

import functools  def log_cost_time(func):      @functools.wraps(func)      def wrapped(*args, **kwargs):          import time          begin = time.time()          try:              return func(*args, **kwargs)          finally:              print 'func %s cost %s' % (func.__name__, time.time() - begin)      return wrapped

再查看complex_func.__name__ 輸出就是 “complex_func”

裝飾器也是可以帶參數的。我們將上面的代碼略微修改一下:

def log_cost_time(stream):      def inner_dec(func):          def wrapped(*args, **kwargs):              import time              begin = time.time()              try:                  return func(*args, **kwargs)              finally:                  stream.write('func %s cost %s \n' % (func.__name__, time.time() - begin))          return wrapped      return inner_dec     import sys  @log_cost_time(sys.stdout)  def complex_func(num):      ret = 0      for i in xrange(num):          ret += i * i      return ret     if __name__ == '__main__':      print complex_func(100000)     code snippet 1

log_cost_time函數也接受一個參數,該參數用來指定信息的輸出流,對于帶參數的decorator

@dec(dec_args)  def func(*args, **kwargs):pass

等價于 func = dec(dec_args)(*args, **kwargs)。

裝飾器對類的修飾也是很簡單的,只不過平時用得不是很多。舉個例子,我們需要給修改類的__str__方法,代碼很簡單。

def Haha(clz):      clz.__str__ = lambda s: "Haha"      return clz     @Haha  class Widget(object):      ''' class Widget '''     if __name__ == '__main__':      w = Widget()      print w

那什么場景下有必要使用decorator呢,設計模式中有一個模式也叫裝飾器。我們先簡單回顧一下設計模式中的裝飾器模式,簡單的一句話概述

動態地為某個對象增加額外的責任

由于裝飾器模式僅從外部改變組件,因此組件無需對它的裝飾有任何了解;也就是說,這些裝飾對該組件是透明的。

下圖來自《設計模式Java手冊》或者GOF的《設計模式》

Python中Decorator的作用是什么

回到Python中來,用decorator語法實現裝飾器模式是很自然的,比如文中的示例代碼,在不改變被裝飾對象的同時增加了記錄函數執行時間的額外功能。當然,由于Python語言的靈活性,decorator是可以修改被裝飾的對象的(比如裝飾類的例子)。decorator在python中用途非常廣泛,下面列舉幾個方面:

(1)修改被裝飾對象的屬性或者行為

(2)處理被函數對象執行的上下文,比如設置環境變量,加log之類

(3)處理重復的邏輯,比如有N個函數都可能跑出異常,但是我們不關心這些異常,只要不向調用者傳遞異常就行了,這個時候可以寫一個catchall的decorator,作用于所用可能跑出異常的函數

def catchall(func):      @functools.wraps(func)      def wrapped(*args, **kwargs):          try:              return func(*args, **kwargs)          except:              pass      return wrapped

以上就是Python中Decorator的作用是什么,小編相信有部分知識點可能是我們日常工作會見到或用到的。希望你能通過這篇文章學到更多知識。更多詳情敬請關注億速云行業資訊頻道。

向AI問一下細節

免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。

AI

兰考县| 广水市| 富源县| 五河县| 福州市| 交口县| 米脂县| 光山县| 庆城县| 甘南县| 铜梁县| 桦南县| 安吉县| 甘孜县| 迁安市| 南京市| 富裕县| 佳木斯市| 汝城县| 镇康县| 乌拉特中旗| 应用必备| 晋中市| 赞皇县| 南华县| 田东县| 中牟县| 农安县| 长阳| 龙川县| 长垣县| 武安市| 田阳县| 文水县| 合山市| 廊坊市| 仁化县| 镇宁| 天镇县| 隆回县| 疏附县|