国产探花免费观看_亚洲丰满少妇自慰呻吟_97日韩有码在线_资源在线日韩欧美_一区二区精品毛片,辰东完美世界有声小说,欢乐颂第一季,yy玄幻小说排行榜完本

首頁 > 編程 > Python > 正文

詳解Python中的裝飾器、閉包和functools的教程

2020-02-23 00:30:32
字體:
供稿:網(wǎng)友

裝飾器(Decorators)

裝飾器是這樣一種設(shè)計模式:如果一個類希望添加其他類的一些功能,而不希望通過繼承或是直接修改源代碼實現(xiàn),那么可以使用裝飾器模式。簡單來說Python中的裝飾器就是指某些函數(shù)或其他可調(diào)用對象,以函數(shù)或類作為可選輸入?yún)?shù),然后返回函數(shù)或類的形式。通過這個在Python2.6版本中被新加入的特性可以用來實現(xiàn)裝飾器設(shè)計模式。

順便提一句,在繼續(xù)閱讀之前,如果你對Python中的閉包(Closure)概念不清楚,請查看本文結(jié)尾后的附錄,如果沒有閉包的相關(guān)概念,很難恰當(dāng)?shù)睦斫釶ython中的裝飾器。

在Python中,裝飾器被用于用@語法糖修辭的函數(shù)或類。現(xiàn)在讓我們用一個簡單的裝飾器例子來演示如何做一個函數(shù)調(diào)用日志記錄器。在這個例子中,裝飾器將時間格式作為輸入?yún)?shù),在調(diào)用被這個裝飾器裝飾的函數(shù)時打印出函數(shù)調(diào)用的時間。這個裝飾器當(dāng)你需要手動比較兩個不同算法或?qū)崿F(xiàn)的效率時很有用。
 

def logged(time_format):  def decorator(func):   def decorated_func(*args, **kwargs):     print "- Running '%s' on %s " % (                     func.__name__,                     time.strftime(time_format)               )     start_time = time.time()     result = func(*args, **kwargs)     end_time = time.time()     print "- Finished '%s', execution time = %0.3fs " % (                     func.__name__,                     end_time - start_time               )      return result   decorated_func.__name__ = func.__name__   return decorated_func return decorator

來看一個例子,在這里add1和add2函數(shù)被logged修飾,下面給出了一個輸出示例。請注意在這里時間格式參數(shù)是存儲在被返回的裝飾器函數(shù)中(decorated_func)。這就是為什么理解閉包對于理解裝飾器來說很重要的原因。同樣也請注意返回函數(shù)的名字是如何被替換為原函數(shù)名的,以防萬一如果它還要被使用到,這是為了防止混淆。Python默認(rèn)可不會這么做。

@logged("%b %d %Y - %H:%M:%S")def add1(x, y):  time.sleep(1)  return x + y @logged("%b %d %Y - %H:%M:%S")def add2(x, y):  time.sleep(2)  return x + y print add1(1, 2)print add2(1, 2) # Output:- Running 'add1' on Jul 24 2013 - 13:40:47- Finished 'add1', execution time = 1.001s3- Running 'add2' on Jul 24 2013 - 13:40:48- Finished 'add2', execution time = 2.001s3

如果你足夠細(xì)心,你可能會注意到我們對于返回函數(shù)的名字__name__有著特別的處理,但對其他的注入__doc__或是__module__則沒有如此。所以如果,在這個例子中add函數(shù)有一個doc字符串的話,它就會被丟棄。那么該如何處理呢?我們當(dāng)然可以像處理__name__那樣對待所有的字段,不過如果在每個裝飾器內(nèi)都這么做的話未免太繁冗了。這就是為何functools模塊提供了一個名為wraps的裝飾器的原因,那正是為了處理這種情況??赡茉诶斫庋b飾器的過程中會被迷惑,不過當(dāng)你把裝飾器看成是一個接收函數(shù)名作為輸入?yún)?shù)并且返回一個函數(shù),這樣就很好理解了。我們將在下個例子中使用wraps裝飾器而不是手動去處理__name__或其他屬性。

發(fā)表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發(fā)表
主站蜘蛛池模板: 基隆市| 榆林市| 江安县| 手游| 潜江市| 黄冈市| 呼图壁县| 朝阳县| 安多县| 万年县| 丰宁| 汨罗市| 郸城县| 定兴县| 龙山县| 安化县| 固始县| 望江县| 厦门市| 绥宁县| 偃师市| 孝昌县| 庆安县| 井陉县| 行唐县| 汨罗市| 桐庐县| 楚雄市| 秭归县| 金寨县| 邵东县| 彰化市| 定襄县| 睢宁县| 奉节县| 七台河市| 南汇区| 库尔勒市| 灵台县| 天等县| 威信县|