亚洲中字慕日产2020,大陆极品少妇内射AAAAAA,无码av大香线蕉伊人久久,久久精品国产亚洲av麻豆网站

資訊專欄INFORMATION COLUMN

python模塊之functools

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

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

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

functools.cmp_to_key(func)

比較函數(shù)是接收兩個參數(shù)進(jìn)行比較的函數(shù),返回一個負(fù)數(shù)表示<,返回0表示=,返回一個正數(shù)表示>。key函數(shù)接收一個參數(shù)并返回另一個值作為進(jìn)行排序的鍵。
將比較函數(shù)轉(zhuǎn)換為key函數(shù),常在用到key關(guān)鍵字的函數(shù)如sotred(), min(), heapq.nlargest(), itertools,groupby()中使用。cmp_to_key主要作為過渡工具將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ù)時可以節(jié)省函數(shù)執(zhí)行時間。

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

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

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

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

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

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

@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

類裝飾器,包裝在定義了一個或多個富比較排序方法的類上,會補(bǔ)足其他的比較方法。
該類必須定義__lt__(), __le__(), __gt__(), 或__ge__()中至少一個方法,并建議定義__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:使用這個裝飾器的代價是,裝飾器自動補(bǔ)足的比較方法耗費了更多的執(zhí)行時間并擁有更復(fù)雜的堆棧跟蹤。如果應(yīng)用性能基準(zhǔn)測試表明是使用此裝飾器造成的瓶頸,手動實現(xiàn)所有六種富比較方法可以帶來直觀的速度提升。

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

偏函數(shù),返回一個partial對象,調(diào)用時等同調(diào)用了使用預(yù)設(shè)位置參數(shù)和關(guān)鍵字參數(shù)的func函數(shù)。如果partial對象調(diào)用時又提供了額外的位置參數(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)生一個代表某部分函數(shù)功能的簡化標(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])

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

@functools.singledispatch

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

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

from functools import singledispatch

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

使用泛函數(shù)的register()屬性添加重載實現(xiàn),該屬性是一個裝飾器。對于使用類型注解的函數(shù),該裝飾器將自動推斷第一個參數(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()注冊lambda函數(shù)和已定義的函數(shù):

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

fun.register(type(None), nothing)

register()屬性返回允許裝飾器堆疊、序列化以及創(chuàng)建獨立的單元測試的未裝飾的函數(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ù)的類型:

>>> 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

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

>>> fun.dispatch(float)

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

調(diào)用registry屬性查看注冊的所有實現(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),使其看起來更像被包裝的原始函數(shù)(wrapped)。元組類型的可選參數(shù)assigned指定wrapped函數(shù)的哪些屬性直接分派到wrapper函數(shù)對應(yīng)的屬性上,updated參數(shù)指定使用wrapped函數(shù)的哪些屬性更新wrapper函數(shù)對應(yīng)的屬性。

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

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

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

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),不過是作為包裝函數(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對象

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

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

轉(zhuǎn)載請注明本文地址:http://www.ezyhdfw.cn/yun/45040.html

相關(guān)文章

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

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

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

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

    caozhijian 評論0 收藏0
  • 5-functools模塊

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

    YancyYe 評論0 收藏0
  • Python一等函數(shù)簡析

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

    shusen 評論0 收藏0
  • Python一等函數(shù)簡析

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

    鄒立鵬 評論0 收藏0

發(fā)表評論

0條評論

最新活動
閱讀需要支付1元查看
<