Python模块functools学习笔记

一、模块简介

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

三、参考资料

猜你喜欢

转载自blog.csdn.net/weixin_37780776/article/details/106322471