python functools常用方法

functools模塊用于高級函數(shù):作用于或返回其他函數(shù)的函數(shù)赏胚,一般來說,任何可調(diào)用對象都可以作為這個模塊的用途來處理羔巢。

1檩小、lru_cache

@functools.lru_cache(maxsize=128, typed=False)
使用functools模塊的lur_cache裝飾器,可以緩存最多 maxsize 個此函數(shù)的調(diào)用結果杜耙,從而提高程序執(zhí)行的效率搜骡,特別適合于耗時的函數(shù)。參數(shù)maxsize為最多緩存的次數(shù)佑女,如果為None记靡,則無限制,設置為2n時团驱,性能最佳摸吠;如果 typed=True(注意,在 functools32 中沒有此參數(shù))嚎花,則不同參數(shù)類型的調(diào)用將分別緩存寸痢,例如 f(3) 和 f(3.0)。

被 lru_cache 裝飾的函數(shù)會有 cache_clear 和 cache_info 兩個方法紊选,分別用于清除緩存和查看緩存信息啼止。

from functools import lru_cache

@lru_cache(maxsize=32)
def fib(n):
    print('calling the fib function....')
    if n < 2:
        return n
    return fib(n-1) + fib(n-2)



if __name__ == '__main__':
    print(list([fib(n) for n in range(16)]))
    [print(func) for func in dir(fib) if not func.startswith('_')]
    print(fib.cache_info())
    print('------------')
    print([fib(n) for n in range(16)])

運行結果:

image.png

如果把第二次調(diào)用的參數(shù)改為大于16的數(shù),注意看結果

image.png

可以看出兵罢,在已經(jīng)緩存的數(shù)據(jù)中献烦,不會進行重復調(diào)用函數(shù),但是卖词,未被緩存的數(shù)據(jù)將再次調(diào)用函數(shù)仿荆。

2、partial

functools.partial(func, *args, **keywords)
大致如下:

def partial(func, *args, **keywords):
    def newfunc(*fargs, **fkeywords):
        newkeywords = keywords.copy()
        newkeywords.update(fkeywords)
        return func(*(args + fargs), **newkeywords)
    newfunc.func = func
    newfunc.args = args
    newfunc.keywords = keywords
    return newfunc
image.png

可以看出函數(shù)partial的返回值是一個partial類坏平,該類有三個只讀屬性

partial.func:可調(diào)用的對象或函數(shù)
partial.args:最左邊的位置參數(shù)將被預先提交給partial對象調(diào)用所提供的位置參數(shù)
partial.keywords:當調(diào)用partial對象時拢操,將提供關鍵字參數(shù).

3.reduce

functools.reduce(function, iterable[, initializer])
大致如下:

def reduce(function, iterable, initializer=None):
    it = iter(iterable)
    if initializer is None:
        value = next(it)
    else:
        value = initializer
    for element in it:
        value = function(value, element)
    return value
image.png

4.update_wrapper

functools.update_wrapper(wrapper, wrapped, assigned=WRAPPER_ASSIGNMENTS, updated=WRAPPER_UPDATES)
找不到很好的解釋該函數(shù)的材料,于是舶替,看了一下源碼:

WRAPPER_ASSIGNMENTS = ('__module__', '__name__', '__doc__')
WRAPPER_UPDATES = ('__dict__',)
def update_wrapper(wrapper,
                   wrapped,
                   assigned = WRAPPER_ASSIGNMENTS,
                   updated = WRAPPER_UPDATES):
    """Update a wrapper function to look like the wrapped function

       wrapper is the function to be updated
       wrapped is the original function
       assigned is a tuple naming the attributes assigned directly
       from the wrapped function to the wrapper function (defaults to
       functools.WRAPPER_ASSIGNMENTS)
       updated is a tuple naming the attributes of the wrapper that
       are updated with the corresponding attribute from the wrapped
       function (defaults to functools.WRAPPER_UPDATES)
    """
    for attr in assigned:
        setattr(wrapper, attr, getattr(wrapped, attr))
    for attr in updated:
        getattr(wrapper, attr).update(getattr(wrapped, attr, {}))
    # Return the wrapper so this can be used as a decorator via partial()
    return wrapper

5.wraps

@functools.wraps(wrapped, assigned=WRAPPER_ASSIGNMENTS, updated=WRAPPER_UPDATES)
是不是覺得這坨跟update_wrapper很像令境,是的,他其實調(diào)用了update_wrapper,像下面:

def wraps(wrapped,
          assigned = WRAPPER_ASSIGNMENTS,
          updated = WRAPPER_UPDATES):
    """Decorator factory to apply update_wrapper() to a wrapper function

       Returns a decorator that invokes update_wrapper() with the decorated
       function as the wrapper argument and the arguments to wraps() as the
       remaining arguments. Default arguments are as for update_wrapper().
       This is a convenience function to simplify applying partial() to
       update_wrapper().
    """
    return partial(update_wrapper, wrapped=wrapped,
                   assigned=assigned, updated=updated)

怎么樣顾瞪,使用partial固定住三個關鍵字參數(shù)以后,開始使用update_wrapper函數(shù)調(diào)用舔庶,只需傳入wrapper參數(shù)即可。具體例子說明會更清晰:

from functools import update_wrapper,wraps


def my_decorator1(f):
     def wrapper(*args, **kwds):
         print('Calling decorated function')
         return f(*args, **kwds)
     return update_wrapper(wrapper=wrapper ,wrapped=f)

def my_decorator2(f):
    @wraps(f)
    def wrapper(*args, **kwds):
        print('Calling decorated function')
        return f(*args, **kwds)
    return wrapper


@my_decorator1
def example():
    """Docstring"""
    print('Called example function')

if __name__ == '__main__':
    # process result:
    # Calling decorated function
    # Called example function
    example()
    # add wraps decorator reuslt is :example Docstring __main__
    # print example.__name__, example.__doc__, example.__module__
    # not add wraps decorator reuslt is :wrapper None __main__
    print('example_name: %s, example_doc: %s, example_module: %s '%(example.__name__, example.__doc__, example.__module__))                                                                                                                     

上面的例子中陈醒,wraps裝飾器的參數(shù)是my_decorator2裝飾器的參數(shù)惕橙,本例中也是example函數(shù),在wraps調(diào)用partial函數(shù)時钉跷,wrapped參數(shù)值就賦值為example函數(shù)弥鹦。我們知道wraps函數(shù)的返會結果是可調(diào)用partial對象,該對象的func屬性時update_wrapper.所以my_decorator2的功能實際上和my_decorator1功能是相同的。

最后編輯于
?著作權歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末彬坏,一起剝皮案震驚了整個濱河市朦促,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌栓始,老刑警劉巖务冕,帶你破解...
    沈念sama閱讀 212,686評論 6 492
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異幻赚,居然都是意外死亡禀忆,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,668評論 3 385
  • 文/潘曉璐 我一進店門落恼,熙熙樓的掌柜王于貴愁眉苦臉地迎上來油湖,“玉大人,你說我怎么就攤上這事领跛》Φ拢” “怎么了?”我有些...
    開封第一講書人閱讀 158,160評論 0 348
  • 文/不壞的土叔 我叫張陵吠昭,是天一觀的道長喊括。 經(jīng)常有香客問我,道長矢棚,這世上最難降的妖魔是什么郑什? 我笑而不...
    開封第一講書人閱讀 56,736評論 1 284
  • 正文 為了忘掉前任,我火速辦了婚禮蒲肋,結果婚禮上蘑拯,老公的妹妹穿的比我還像新娘。我一直安慰自己兜粘,他們只是感情好申窘,可當我...
    茶點故事閱讀 65,847評論 6 386
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著孔轴,像睡著了一般剃法。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上路鹰,一...
    開封第一講書人閱讀 50,043評論 1 291
  • 那天贷洲,我揣著相機與錄音,去河邊找鬼晋柱。 笑死优构,一個胖子當著我的面吹牛,可吹牛的內(nèi)容都是我干的雁竞。 我是一名探鬼主播钦椭,決...
    沈念sama閱讀 39,129評論 3 410
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了玉凯?” 一聲冷哼從身側響起势腮,我...
    開封第一講書人閱讀 37,872評論 0 268
  • 序言:老撾萬榮一對情侶失蹤联贩,失蹤者是張志新(化名)和其女友劉穎漫仆,沒想到半個月后,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體泪幌,經(jīng)...
    沈念sama閱讀 44,318評論 1 303
  • 正文 獨居荒郊野嶺守林人離奇死亡盲厌,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 36,645評論 2 327
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了祸泪。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片吗浩。...
    茶點故事閱讀 38,777評論 1 341
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖没隘,靈堂內(nèi)的尸體忽然破棺而出懂扼,到底是詐尸還是另有隱情,我是刑警寧澤右蒲,帶...
    沈念sama閱讀 34,470評論 4 333
  • 正文 年R本政府宣布阀湿,位于F島的核電站,受9級特大地震影響瑰妄,放射性物質(zhì)發(fā)生泄漏陷嘴。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 40,126評論 3 317
  • 文/蒙蒙 一间坐、第九天 我趴在偏房一處隱蔽的房頂上張望灾挨。 院中可真熱鬧,春花似錦竹宋、人聲如沸劳澄。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,861評論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽浴骂。三九已至,卻和暖如春宪潮,著一層夾襖步出監(jiān)牢的瞬間溯警,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 32,095評論 1 267
  • 我被黑心中介騙來泰國打工狡相, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留梯轻,地道東北人。 一個月前我還...
    沈念sama閱讀 46,589評論 2 362
  • 正文 我出身青樓尽棕,卻偏偏與公主長得像喳挑,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 43,687評論 2 351

推薦閱讀更多精彩內(nèi)容

  • 1 functools函數(shù) functools模塊用于高階函數(shù):作用與或者返回其它函數(shù)的函數(shù)伊诵。一般來說单绑,對于該模塊...
    lakerszhy閱讀 9,981評論 0 7
  • //Clojure入門教程: Clojure – Functional Programming for the J...
    葡萄喃喃囈語閱讀 3,636評論 0 7
  • 每日問答:今天你的努力配的上你想要的生活和想愛的人嗎?答:配不上曹宴,今天玩了1小時游戲搂橙,還有今天的簡歷還是沒寫完 學...
    鑄劍僧閱讀 112評論 0 1
  • 2017年8月30日 星期三 深圳 天氣 晴 今天是多么美好的一天扒!充滿著愛版扩!熱情废离!效益!感恩礁芦!Po...
    dm小梅閱讀 339評論 2 1