天天看點

Python子產品functools學習筆記一、子產品簡介二、子產品函數三、參考資料

文章目錄

  • 一、子產品簡介
  • 二、子產品函數
    • 1. `functools.lru_cache(maxsize=128, typed=False)`
    • 2. `functools.partial(func, /, *args, **keywords)`
    • 3. `functools.update_wrapper`
    • 4. `@functools.wraps`
      • 4.1 裝飾器原型
      • 4.2 裝飾器定義
      • 4.3 裝飾器應用
  • 三、參考資料

一、子產品簡介

The functools module is for higher-order functions: functions that act on or return other functions.

functools子產品用于高階函數,高階函數顧名思義也是一種函數,不同的是,高階函數可以作用于或者傳回其他函數。

二、子產品函數

1.

functools.lru_cache(maxsize=128, typed=False)

2.

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

3.

functools.update_wrapper

4.

@functools.wraps

這是一個裝飾器。

4.1 裝飾器原型

@functools.wraps(wrapped, assigned=WRAPPER_ASSIGNMENTS, updated=WRAPPER_UPDATES)

4.2 裝飾器定義

  • This is a convenience function for invoking update_wrapper() as a function decorator when defining a wrapper function.

    在定義裝飾器函數内部的嵌套函數時,在嵌套函數上方使用@functools.wraps()相當于調用函數functools.update_wrapper()

  • It is equivalent to partial(update_wrapper, wrapped=wrapped, assigned=assigned, updated=updated).

    這相當于partial(update_wrapper, wrapped=wrapped, assigned=assigned, updated=updated)

4.3 裝飾器應用

在Python裝飾器從初識到精通中,我們知道使用裝飾器可以為代碼編寫帶來很大的便利, 但是使用裝飾器時,也可能會影響到Python中的自省特性(特别在使用互動式Python shell時會用到該特性),這就可以通過使用@functools.wraps()裝飾器來解決。

  • 自省的概念:
所謂自省是指,Python中對象可以在運作時知道其各類屬性。如:一個函數知道其自身名稱以及幫助文檔内容。

如:

In [1]: print
Out[1]: <function print>

In [2]: print.__name__
Out[2]: 'print'

In [3]: help(print)
           
  • 自省的使用:

自省特性同樣适用于使用者自定義的函數,如:

In [5]: say_whee
Out[5]: <function __main__.say_whee>

In [6]: say_whee.__name__
Out[6]: 'say_whee'
           
  • 當自省遇到裝飾器:

但問題是:當對自定義函數使用裝飾器後,将對say_whee()函數的自省特性産生影響,如:

def do_twice(func):
    """該裝飾器用于将被裝飾函數執行兩次"""
    def wrapper(*args, **kwargs):
        func(*args, **kwargs)
        func(*args, **kwargs)

    return wrapper


@do_twice
def say_whee():
    """這是一個簡單的被裝飾函數"""
    print("Whee!")


say_whee()
print("執行print(say_whee)後的結果為:")
print(say_whee, end="\n" * 2)
print("執行print(say_whee.__name__)後的結果為:")
print(say_whee.__name__, end="\n" * 2)
print("執行print(help(say_whee))後的結果為:")
print(help(say_whee))

           

上述程式的執行結果為:

Whee!

Whee!

執行print(say_whee)後的結果為:

<function do_twice.<locals>.wrapper at 0x7fe48aa679d8>

執行print(say_whee.__name__)後的結果為:

wrapper

執行print(help(say_whee))後的結果為:

Help on function wrapper in module __main__:

wrapper(*args, **kwargs)

None

即:由于對函數say_whee使用了裝飾器do_twice的緣故,導緻其原本的屬性被遺失。

  • 裝飾器産生的問題用裝飾器來解決:

使用@functools.wraps()裝飾器即可以解決此問題(用魔法來打敗魔法),如:

import functools


def do_twice(func):
    """該裝飾器用于将被裝飾函數執行兩次"""
    @functools.wraps(func)
    def wrapper(*args, **kwargs):
        func(*args, **kwargs)
        func(*args, **kwargs)

    return wrapper


@do_twice
def say_whee():
    """這是一個簡單的被裝飾函數"""
    print("Whee!")


say_whee()
print("執行print(say_whee)後的結果為:")
print(say_whee, end="\n" * 2)
print("執行print(say_whee.__name__)後的結果為:")
print(say_whee.__name__, end="\n" * 2)
print("執行print(help(say_whee))後的結果為:")
print(help(say_whee))

           

上述代碼的執行結果為:

Whee!

Whee!

執行print(say_whee)後的結果為:

<function say_whee at 0x7f1360f8da60>

執行print(say_whee.name)後的結果為:

say_whee

執行print(help(say_whee))後的結果為:

Help on function say_whee in module main:

say_whee()

這是一個簡單的被裝飾函數

None

三、參考資料

  • [1] Primer on Python Decorators