functools模塊學(xué)習(xí)

1. partial(func, /, *args, **kwargs)

  • 封裝原函數(shù)并返回一個partial object對象, 可直接調(diào)用
  • 固定原函數(shù)的部分參數(shù), 相當(dāng)于為原函數(shù)添加了固定的默認(rèn)值
    相當(dāng)于如下代碼:
def partial(func, /, *args, **kwargs):
    def newfunc(*fargs, **fkwargs):
        newkwargs = {**kwargs, **fkwargs}
        return func(*args, *fargs, **newkwargs)
    newfunc.func = func
    newfunc.args = args
    newfunc.kwargs = kwargs
    return newfunc

例如, 需要一個默認(rèn)轉(zhuǎn)換二進(jìn)制的int()函數(shù):

>>> from functools import partial
>>> basetwo = partial(int, base=2)
>>> basetwo.__doc__ = 'Convert base 2 string to an int.'
>>> basetwo('10010')
18

2. partialmethod(func, /, *args, **kwargs)

  • partial用法相同, 專門用于類定義中(由于類定義中第一個參數(shù)默認(rèn)需要self/cls, 所以partial不適用)
  • 在類中, 不論普通方法, staticmethod, classmethod還是abstractmethod都適用

例如:

class Cell:
    def __init__(self):
        self._alive = False
    
    @property
    def alive(self):
        return self._alive
    
    def set_alive(self, state):
        self._alive = bool(state)
    set_alive = partialmethod(set_state, True)
    set_dead = partialmethod(set_state, False)

>>> c = Cell()
>>> c.alive
False
>>> c.set_alive()
>>> c.alive
True

3. update_wrapper(wrapper, warpped, assigned=WRAPPER_ASSIGNMEDTS, updated=WRAPPER_UPDATES)

  • 更新裝飾函數(shù)(wrapper), 使其看起來更像被裝飾函數(shù)(wrapped)
  • 主要用在裝飾器中, 包裹被裝飾函數(shù), 并返回一個更新后的裝飾函數(shù). 如果裝飾函數(shù)沒有更新, 那么返回的函數(shù)的元數(shù)據(jù)將來自裝飾器, 而不是原始函數(shù)
  • 兩個可選參數(shù)用來指定原始函數(shù)的哪些屬性直接賦值給裝飾函數(shù), 哪些屬性需要裝飾函數(shù)做相應(yīng)的更新. 默認(rèn)值是模塊級常量WRAPPER_ASSIGNMENTS(賦值裝飾函數(shù)的__module__, __name__, __qualname__, __annotations____doc__屬性)和WRAPPER_UpDATED(更新裝飾函數(shù)的__dict__屬性)

4. wraps(wrapped, assigned=WRAPPER_ASSIGNMENTS, updasted=WRAPPER_UPDATES)

  • 簡化調(diào)用update_wrapper的過程, 作為裝飾器使用
  • 相當(dāng)于partial(update_wrapper, wrapped=wrapped, assigned=assigned, updated=updated)

例如:

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

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

>>> example()
Calling decorated function
Called example function
>>> example.__name__
'example'
>>> example.__doc__
'Docstring'

如果沒有使用wraps, 那么被裝飾函數(shù)的名字將會是wrapper, 而且原始函數(shù)example的文檔字符串將會丟失.

5. singledispatch(func)

  • 作為裝飾器使用, 將被裝飾函數(shù)轉(zhuǎn)換為一個泛函數(shù)(generic function)
  • 根據(jù)第一個參數(shù)的類型分派執(zhí)行不同的操作

例如:

@singledispatch
def fun(arg, verbose=False):
    if verbose:
        print('Let me just say,', end='')
    print(arg)

@fun.register(int)
def _(arg, verbose=False):
    if verbose:
        print('Strength in numbers, eh?', end='')
    print(arg)

@fun.register(list)
def _(arg, verbose=False)
    if verbose:
        print('Enumerate this: ')
    for i, elem in enumerate(arg):
        print(i, elem)


>>> fun('Hello World')
Hello World
>>> fun('test', verbose=True)
Let me just say, test
>>> fun(123, verbose=True)
Strength in numbers, eh? 123
>>> fun(['Issac', 'Chaplin', 'Mr Bean'], verbose=True)
Enumerate this:
0 Issac
1 Chaplin
2 Mr Bean

可以使用"函數(shù)類型注釋"替代上面顯式指定類型

@fun.register
def _(arg: int, verbose=False):
    pass

6. singledispatchmethod(func)

  • 將方法裝飾為泛函數(shù)
  • 根據(jù)第一個非self或非cls參數(shù)的類型分派執(zhí)行不同的操作
  • 可以與其他裝飾器嵌套使用, 但singledispatchmethod,dispatcher.register必須在最外層
  • 其他用法與singledispatch相同

例如:

class Negator:
    @singledispatchmethod
    @classmethod
    def neg(cls, arg):
        raise NotImplementedError("Cannot negate a")
    
    @neg.register
    @classmethod
    def _(cls, arg: int):
        return -arg
    
    @neg.register
    @classmethod
    def _(cls, arg: bool):
        return not arg

7. cached_property(func)

  • 將方法轉(zhuǎn)換為一個屬性, 與@property相似
  • 被裝飾的方法僅計算一次, 之后作為普通實例屬性被緩存
  • 要求實例擁有可變的__dict__屬性(在元類或聲明的__slots__中未包含__dict__的類中不可用)

例如:

class DataSet:
    def __init__(self, sequence_of_numbers):
        self._data = sequence_of_numbers
    
    @cached_property
    def stdev(self):
        return statistics.stdev(self._data)
    
    @cached_property
    def variance(self):
        return statistics.variance(self._data)

cached_property的底層是一個非數(shù)據(jù)描述符, 在func第一次計算時, 將結(jié)果保存在實例的一個同名屬性中(實例的__dict__中), 由于實例屬性的優(yōu)先級大于非數(shù)據(jù)描述符, 之后的所有調(diào)用只直接取實例屬性而不會再次計算

8. lru_cache(user_function) / lru_cache(maxsize=128, typed=False)

  • 緩存被裝飾函數(shù)的最近maxsize次的調(diào)用結(jié)果
  • maxsize如果設(shè)置為None, LRU緩存機(jī)制將不可用, 緩存會無限增長.maxsize的值最好是2的n次冪
  • 由于底層使用字典緩存結(jié)果, 所以被裝飾函數(shù)的參數(shù)必須可哈希.
  • 不同的參數(shù)模式會分開緩存為不用的條目, 例如f(a=1, b=2)f(b=2, a=1)就會作為兩次緩存
  • 如果typed設(shè)置為True, 不同類型的函數(shù)參數(shù)將會被分開緩存, 例如f(3)f(3.0)

例如:

@lru_cache(maxsize=None)
def fib(n):
    if n < 2:
        return n
    return fib(n-1) + fib(n-2)

>>> [fib(n) for n in range(16)]
[0, 1, 1, 2, 3, 5, 8, 13, 21, 34, 55, 89, 144, 233, 377, 610]
>>> fib.cache_info()
CacheInfo(hits=28, misses=16, maxsize=None, currsize=16)
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市劫拢,隨后出現(xiàn)的幾起案子肉津,更是在濱河造成了極大的恐慌强胰,老刑警劉巖,帶你破解...
    沈念sama閱讀 217,542評論 6 504
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件妹沙,死亡現(xiàn)場離奇詭異偶洋,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī)初烘,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,822評論 3 394
  • 文/潘曉璐 我一進(jìn)店門涡真,熙熙樓的掌柜王于貴愁眉苦臉地迎上來分俯,“玉大人肾筐,你說我怎么就攤上這事「准簦” “怎么了吗铐?”我有些...
    開封第一講書人閱讀 163,912評論 0 354
  • 文/不壞的土叔 我叫張陵,是天一觀的道長杏节。 經(jīng)常有香客問我唬渗,道長,這世上最難降的妖魔是什么奋渔? 我笑而不...
    開封第一講書人閱讀 58,449評論 1 293
  • 正文 為了忘掉前任镊逝,我火速辦了婚禮,結(jié)果婚禮上嫉鲸,老公的妹妹穿的比我還像新娘撑蒜。我一直安慰自己,他們只是感情好玄渗,可當(dāng)我...
    茶點故事閱讀 67,500評論 6 392
  • 文/花漫 我一把揭開白布座菠。 她就那樣靜靜地躺著,像睡著了一般藤树。 火紅的嫁衣襯著肌膚如雪浴滴。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 51,370評論 1 302
  • 那天岁钓,我揣著相機(jī)與錄音升略,去河邊找鬼。 笑死屡限,一個胖子當(dāng)著我的面吹牛降宅,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播囚霸,決...
    沈念sama閱讀 40,193評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼腰根,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了拓型?” 一聲冷哼從身側(cè)響起额嘿,我...
    開封第一講書人閱讀 39,074評論 0 276
  • 序言:老撾萬榮一對情侶失蹤瘸恼,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后册养,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體东帅,經(jīng)...
    沈念sama閱讀 45,505評論 1 314
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,722評論 3 335
  • 正文 我和宋清朗相戀三年球拦,在試婚紗的時候發(fā)現(xiàn)自己被綠了靠闭。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 39,841評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡坎炼,死狀恐怖愧膀,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情谣光,我是刑警寧澤檩淋,帶...
    沈念sama閱讀 35,569評論 5 345
  • 正文 年R本政府宣布,位于F島的核電站萄金,受9級特大地震影響蟀悦,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜氧敢,卻給世界環(huán)境...
    茶點故事閱讀 41,168評論 3 328
  • 文/蒙蒙 一日戈、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧孙乖,春花似錦浙炼、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,783評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至越妈,卻和暖如春季俩,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背梅掠。 一陣腳步聲響...
    開封第一講書人閱讀 32,918評論 1 269
  • 我被黑心中介騙來泰國打工酌住, 沒想到剛下飛機(jī)就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人阎抒。 一個月前我還...
    沈念sama閱讀 47,962評論 2 370
  • 正文 我出身青樓酪我,卻偏偏與公主長得像,于是被迫代替她去往敵國和親且叁。 傳聞我的和親對象是個殘疾皇子脉漏,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 44,781評論 2 354

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