成人国产在线小视频_日韩寡妇人妻调教在线播放_色成人www永久在线观看_2018国产精品久久_亚洲欧美高清在线30p_亚洲少妇综合一区_黄色在线播放国产_亚洲另类技巧小说校园_国产主播xx日韩_a级毛片在线免费

資訊專欄INFORMATION COLUMN

python模塊之functools

騫諱護(hù) / 1302人閱讀

摘要:比較函數(shù)是接收兩個(gè)參數(shù)進(jìn)行比較的函數(shù),返回一個(gè)負(fù)數(shù)表示,返回表示,返回一個(gè)正數(shù)表示。表示緩存大小限制,確保不會(huì)無(wú)限制增長(zhǎng)。大致等同于用于凍結(jié)函數(shù)的部分位置參數(shù)和或關(guān)鍵字參數(shù)而產(chǎn)生一個(gè)代表某部分函數(shù)功能的簡(jiǎn)化標(biāo)志。

functools模塊提供了某些高階函數(shù)(high-order function)。

functools.cmp_to_key(func)

比較函數(shù)是接收兩個(gè)參數(shù)進(jìn)行比較的函數(shù),返回一個(gè)負(fù)數(shù)表示<,返回0表示=,返回一個(gè)正數(shù)表示>。key函數(shù)接收一個(gè)參數(shù)并返回另一個(gè)值作為進(jìn)行排序的鍵。
將比較函數(shù)轉(zhuǎn)換為key函數(shù),常在用到key關(guān)鍵字的函數(shù)如sotred(), min(), heapq.nlargest(), itertools,groupby()中使用。cmp_to_key主要作為過(guò)渡工具將python2中支持的比較函數(shù)進(jìn)行轉(zhuǎn)換。

def numeric_compare(x, y):
    return x - y

# python2
print(sorted([5, 2, 4, 1, 3], cmp=numeric_compare))

# python3
print(sorted([5, 2, 4, 1, 3], key=cmp_to_key(numeric_compare)))
@functools.lru_cache(maxsize=128, typed=False)

使用memoize包裝函數(shù),保存最近maxsize次的函數(shù)調(diào)用結(jié)果。在I/O-bound函數(shù)上裝飾,處理相同參數(shù)時(shí)可以節(jié)省函數(shù)執(zhí)行時(shí)間。

如果maxsize為None,會(huì)禁用LRU緩存特性(并非禁用緩存)且緩存大小會(huì)無(wú)限增長(zhǎng)。maxsize設(shè)置為2的n次方時(shí)性能最優(yōu)。

如果typed為T(mén)rue,不同類型函數(shù)參數(shù)的執(zhí)行結(jié)果會(huì)被分別緩存,例如f(3)f(3.0)會(huì)被視為有兩個(gè)不同結(jié)果的不同調(diào)用。

因?yàn)樵撗b飾器使用字典緩存函數(shù)執(zhí)行結(jié)果,所以函數(shù)的位置參數(shù)和關(guān)鍵字參數(shù)必須是可哈希的。

不同的參數(shù)模式可能會(huì)被視為不同的緩存實(shí)體。例如f(a=1, b=2)f(b=2, a=1)雖然只是關(guān)鍵字順序不同但可能有兩個(gè)多帶帶的緩存實(shí)體。

被包裝的函數(shù)可以調(diào)用cache_info(),它返回一個(gè)(hits, misses, maxsize, currsize)形式的命名元組;可以調(diào)用cache_clear()清空或使緩存無(wú)效;還可以調(diào)用__wrapped__屬性繞過(guò)緩存,訪問(wèn)原始的底層函數(shù)。

LRU(least recently used)緩存通常應(yīng)僅用在需要重用先前計(jì)算的值的場(chǎng)景,其他場(chǎng)景如使用LRU有不良影響、每次調(diào)用需要返回不同結(jié)果、time()、random()等應(yīng)禁止使用。maxsize表示緩存大小限制,確保不會(huì)無(wú)限制增長(zhǎng)。

@lru_cache(maxsize=32)
def get_pep(num):
    "Retrieve text of a Python Enhancement Proposal"
    resource = "http://www.python.org/dev/peps/pep-%04d/" % num
    try:
        with urllib.request.urlopen(resource) as s:
            return s.read()
    except urllib.error.HTTPError:
        return "Not Found"

>>> for n in 8, 290, 308, 320, 8, 218, 320, 279, 289, 320, 9991:
...     pep = get_pep(n)
...     print(n, len(pep))

>>> get_pep.cache_info()
CacheInfo(hits=3, misses=8, maxsize=32, currsize=8)
@functools.total_ordering

類裝飾器,包裝在定義了一個(gè)或多個(gè)富比較排序方法的類上,會(huì)補(bǔ)足其他的比較方法。
該類必須定義__lt__(), __le__(), __gt__(), 或__ge__()中至少一個(gè)方法,并建議定義__eq__()方法。

@total_ordering
class Student:
    def __init__(self, lastname, firstname):
        self.lastname = lastname
        self.firstname = firstname

    def _is_valid_operand(self, other):
        return (hasattr(other, "lastname") and
                hasattr(other, "firstname"))

    def __eq__(self, other):
        if not self._is_valid_operand(other):
            return NotImplemented
        return ((self.lastname.lower(), self.firstname.lower()) ==
                (other.lastname.lower(), other.firstname.lower()))

    def __lt__(self, other):
        if not self._is_valid_operand(other):
            return NotImplemented
        return ((self.lastname.lower(), self.firstname.lower()) <
                (other.lastname.lower(), other.firstname.lower()))

NOTE:使用這個(gè)裝飾器的代價(jià)是,裝飾器自動(dòng)補(bǔ)足的比較方法耗費(fèi)了更多的執(zhí)行時(shí)間并擁有更復(fù)雜的堆棧跟蹤。如果應(yīng)用性能基準(zhǔn)測(cè)試表明是使用此裝飾器造成的瓶頸,手動(dòng)實(shí)現(xiàn)所有六種富比較方法可以帶來(lái)直觀的速度提升。

functools.partial(func, *args, **keywords)

偏函數(shù),返回一個(gè)partial對(duì)象,調(diào)用時(shí)等同調(diào)用了使用預(yù)設(shè)位置參數(shù)和關(guān)鍵字參數(shù)的func函數(shù)。如果partial對(duì)象調(diào)用時(shí)又提供了額外的位置參數(shù),追加到args,如果提供了額外的關(guān)鍵字參數(shù),擴(kuò)展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

partial()用于"凍結(jié)"函數(shù)的部分位置參數(shù)和/或關(guān)鍵字參數(shù)而產(chǎn)生一個(gè)代表某部分函數(shù)功能的簡(jiǎn)化標(biāo)志。

>>> from functools import partial
>>> basetwo = partial(int, base=2)
>>> basetwo.__doc__ = "Convert base 2 string to an int."
>>> basetwo("10010")
18
class functools.partialmethod(func, *args, **keywords)

后續(xù)補(bǔ)充

functools.reduce(function, iterable[, initializer])

將可迭代對(duì)象iterable中的元素從左到右累計(jì)到接收兩個(gè)參數(shù)的函數(shù)func中。例如reduce(lambda x, y: x+y, [1, 2, 3, 4, 5])的計(jì)算等同于((((1+2)+3)+4)+5)。
如果設(shè)置了可選參數(shù)initializer,它被放置在要計(jì)算的序列之前,并在序列為空時(shí)作為默認(rèn)值;如果未提供initializer的值且序列僅包含一個(gè)元素,返回該元素。

@functools.singledispatch

將函數(shù)轉(zhuǎn)換為單分派泛函數(shù)(single-dispatch generic function)。

使用@singledispatch裝飾器定義一個(gè)泛函數(shù),單分派僅限于第一個(gè)參數(shù)的類型:

from functools import singledispatch

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

使用泛函數(shù)的register()屬性添加重載實(shí)現(xiàn),該屬性是一個(gè)裝飾器。對(duì)于使用類型注解的函數(shù),該裝飾器將自動(dòng)推斷第一個(gè)參數(shù)的類型:

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

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

如果不使用類型注解,可以顯式地給裝飾器傳遞類型參數(shù):

@fun.register(complex)
def _(arg, verbose=False):
    if verbose:
        print("Better than complicated.", end=" ")
    print(arg.real, arg.imag)

也可以以函數(shù)的形式使用register()注冊(cè)lambda函數(shù)和已定義的函數(shù):

def nothing(arg, verbose=False):
    print("Nothing.")

fun.register(type(None), nothing)

register()屬性返回允許裝飾器堆疊、序列化以及創(chuàng)建獨(dú)立的單元測(cè)試的未裝飾的函數(shù):

from decimal import Decimal

@fun.register(float)
@fun.register(Decimal)
def fun_num(arg, verbose=False):
    if verbose:
        print("Half of your number:", end=" ")
    print(arg / 2)

>>> fun_num is fun
False

調(diào)用時(shí),泛函數(shù)只分派第一個(gè)參數(shù)的類型:

>>> fun("Hello, world.")
Hello, world.
>>> fun("test.", verbose=True)
Let me just say, test.
>>> fun(42, verbose=True)
Strength in numbers, eh? 42
>>> fun(["spam", "spam", "eggs", "spam"], verbose=True)
Enumerate this:
0 spam
1 spam
2 eggs
3 spam
>>> fun(None)
Nothing.
>>> fun(1.23)
0.615

如果某個(gè)類型沒(méi)有相應(yīng)的實(shí)現(xiàn),將查找更通用的實(shí)現(xiàn)進(jìn)行解析。使用@singledispatch裝飾的原始函數(shù)注冊(cè)為object類型,將在沒(méi)有更好實(shí)現(xiàn)的情況下使用。調(diào)用dispatch()屬性查看泛函數(shù)使用了哪個(gè)實(shí)現(xiàn):

>>> fun.dispatch(float)

>>> fun.dispatch(dict)    # note: default implementation

調(diào)用registry屬性查看注冊(cè)的所有實(shí)現(xiàn):

>>> fun.registry.keys()
dict_keys([, , , , , ])
>>> fun.registry[float]

>>> fun.registry[object]
functools.update_wrapper(wrapper, wrapped, assigned=WRAPPER_ASSIGNMENTS, updated=WRAPPER_UPDATES)

更新包裝函數(shù)(wrapper),使其看起來(lái)更像被包裝的原始函數(shù)(wrapped)。元組類型的可選參數(shù)assigned指定wrapped函數(shù)的哪些屬性直接分派到wrapper函數(shù)對(duì)應(yīng)的屬性上,updated參數(shù)指定使用wrapped函數(shù)的哪些屬性更新wrapper函數(shù)對(duì)應(yīng)的屬性。

WRAPPER_ASSIGNMENTS的默認(rèn)值是"__module__", "__name__", "__qualname__", "__doc__","__annotations__"
WRAPPER_UPDATES的默認(rèn)值是"__dict__"

通過(guò)訪問(wèn)包裝函數(shù)的__wrapped__屬性可以獲取到被包裝的原始函數(shù)。

該函數(shù)主要用于裝飾器使用場(chǎng)景下,如果不更新包裝函數(shù),返回函數(shù)的元數(shù)據(jù)將指向包裝函數(shù)而非被包裝的原始函數(shù),一般來(lái)說(shuō)沒(méi)太大意義。

def wrapper(f):
    def wrapper_function(*args, **kwargs):
        """this is a wrapper function"""
        return f(*args, **kwargs)
    # update_wrapper(wrapper_function, f)
    return wrapper_function

@wrapper
def wrapped():
    """this is a wrapped function"""
    pass

print(wrapped.__doc__)
print(wrapped.__name__)
# 不使用update_wrapper的結(jié)果:
>>> this is a wrapper function
>>> wrapper_function

# 使用update_wrapper的結(jié)果:
>>> this is a wrapped function
>>> wrapped
@functools.wraps(wrapped, assigned=WRAPPER_ASSIGNMENTS, updated=WRAPPER_UPDATES)

等同于partial(update_wrapper, wrapped=wrapped, assigned=assigned, updated=updated),不過(guò)是作為包裝函數(shù)定義時(shí)的裝飾器使用。

def wrapper(f):
    @wraps(f)
    def wrapper_function(*args, **kwargs):
        """this is a wrapper function"""
        return f(*args, **kwargs)
    return wrapper_function

@wrapper
def wrapped():
    """this is a wrapped function"""
    pass

print(wrapped.__doc__)
print(wrapped.__name__)
partial對(duì)象

partial對(duì)象是由partial()方法創(chuàng)建的可調(diào)用對(duì)象,它有三個(gè)只讀屬性:
partial.func
一個(gè)可調(diào)用對(duì)象或函數(shù)。調(diào)用partial對(duì)象將使用新的位置參數(shù)和關(guān)鍵字參數(shù)轉(zhuǎn)發(fā)到func。
partial.args
調(diào)用partial()時(shí)提供的位置參數(shù)
partial.keywords
調(diào)用partial()時(shí)提供的關(guān)鍵字參數(shù)

文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。

轉(zhuǎn)載請(qǐng)注明本文地址:http://systransis.cn/yun/45040.html

相關(guān)文章

  • Python學(xué)習(xí)路24-一等函數(shù)

    摘要:函數(shù)內(nèi)省的內(nèi)容到此結(jié)束。函數(shù)式編程并不是一個(gè)函數(shù)式編程語(yǔ)言,但通過(guò)和等包的支持,也可以寫(xiě)出函數(shù)式風(fēng)格的代碼。 《流暢的Python》筆記。本篇主要講述Python中函數(shù)的進(jìn)階內(nèi)容。包括函數(shù)和對(duì)象的關(guān)系,函數(shù)內(nèi)省,Python中的函數(shù)式編程。 1. 前言 本片首先介紹函數(shù)和對(duì)象的關(guān)系;隨后介紹函數(shù)和可調(diào)用對(duì)象的關(guān)系,以及函數(shù)內(nèi)省。函數(shù)內(nèi)省這部分會(huì)涉及很多與IDE和框架相關(guān)的東西,如果平時(shí)...

    wind3110991 評(píng)論0 收藏0
  • Python中的函數(shù)裝飾器和閉包

    摘要:變量查找規(guī)則在中一個(gè)變量的查找順序是局部環(huán)境,閉包,全局,內(nèi)建閉包引用了自由變量的函數(shù)。閉包的作用閉包的最大特點(diǎn)是可以將父函數(shù)的變量與內(nèi)部函數(shù)綁定,并返回綁定變量后的函數(shù),此時(shí)即便生成閉包的環(huán)境父函數(shù)已經(jīng)釋放,閉包仍然存在。 導(dǎo)語(yǔ):本文章記錄了本人在學(xué)習(xí)Python基礎(chǔ)之函數(shù)篇的重點(diǎn)知識(shí)及個(gè)人心得,打算入門(mén)Python的朋友們可以來(lái)一起學(xué)習(xí)并交流。 本文重點(diǎn): 1、掌握裝飾器的本質(zhì)、功...

    caozhijian 評(píng)論0 收藏0
  • 5-functools模塊

    摘要:看一個(gè)簡(jiǎn)單的例子在實(shí)際實(shí)驗(yàn)中,加不加并沒(méi)有區(qū)別。僅作了解這是個(gè)有趣的裝飾器,傳入的參數(shù)被打上了,當(dāng)下一次傳入的參數(shù)是一樣的時(shí)候,就會(huì)從中直接取出對(duì)應(yīng)的值,而不需要進(jìn)行重新的運(yùn)算。這樣做的好處是可以幫助我們分離代碼邏輯輸出 functools functools 包含了用于創(chuàng)建裝飾函數(shù),啟動(dòng)面向切面的編程,超出面向?qū)ο缶幊谭秶拇a復(fù)用,同時(shí)提供了裝飾函數(shù)用于豐富的快捷比較的API, p...

    YancyYe 評(píng)論0 收藏0
  • Python一等函數(shù)簡(jiǎn)析

    摘要:本文重點(diǎn)了解函數(shù)在中是一等對(duì)象了解中的可調(diào)用對(duì)象掌握正確定義函數(shù)參數(shù)的方法了解和中支持函數(shù)式編程的方法。歸約函數(shù)定義能夠接受一個(gè)可迭代對(duì)象并返回單個(gè)結(jié)果的函數(shù)是歸約函數(shù)。 導(dǎo)語(yǔ):本文章記錄了本人在學(xué)習(xí)Python基礎(chǔ)之函數(shù)篇的重點(diǎn)知識(shí)及個(gè)人心得,打算入門(mén)Python的朋友們可以來(lái)一起學(xué)習(xí)并交流。 本文重點(diǎn): 1、了解函數(shù)在Python中是一等對(duì)象;2、了解Python中的可調(diào)用對(duì)象;3...

    shusen 評(píng)論0 收藏0
  • Python一等函數(shù)簡(jiǎn)析

    摘要:本文重點(diǎn)了解函數(shù)在中是一等對(duì)象了解中的可調(diào)用對(duì)象掌握正確定義函數(shù)參數(shù)的方法了解和中支持函數(shù)式編程的方法。歸約函數(shù)定義能夠接受一個(gè)可迭代對(duì)象并返回單個(gè)結(jié)果的函數(shù)是歸約函數(shù)。 本文章記錄了本人在學(xué)習(xí)Python基礎(chǔ)之函數(shù)篇的重點(diǎn)知識(shí)及個(gè)人心得,歡迎打算入門(mén)Python的朋友與我一起學(xué)習(xí)交流。。 本文重點(diǎn): 1、了解函數(shù)在Python中是一等對(duì)象;2、了解Python中的可調(diào)用對(duì)象;3、掌握...

    鄒立鵬 評(píng)論0 收藏0

發(fā)表評(píng)論

0條評(píng)論

最新活動(dòng)
閱讀需要支付1元查看
<