python - functools中update_wrapper的使用,装饰器的使用,lambda的混合使用

本文通过两个Python代码示例,深入解析了闭包和装饰器的工作原理。首先,展示了如何使用闭包来创建带有状态的匿名函数,并讨论了在函数内部定义函数的场景。其次,介绍了如何利用装饰器更新函数的元数据,如名称和文档字符串,以保持代码的清晰性和可读性。本文适合对Python高级特性感兴趣的开发者。

代码如下: 

# coding=utf-8
from functools import update_wrapper
nums = [1, 2, 3, 4, 5, 6]


def run(num):
    """啦啦,我是run函数"""
    num += 1
    print num


def test():
    "哈哈,我是test函数"
    for num in nums:
        # func = lambda: run(num)等同于下面的func函数
        def func():
            "呵呵,我是func函数"
            return run(num)
        update_wrapper(func, run)
        # test.__doc__ = str(num) + 'doc'
        # test.__name__ = str(num) + 'name'
        # func.description = 'desc'
        # print func.description
        # func.hehe = 'desc'
        # print func.hehe
        yield func


if __name__ == "__main__":
    for f in test():
        f()
        print f.__doc__
        print f.__name__
    # print test.__doc__
    # print test.__name__

输出结果:

2
啦啦,我是run函数
run
3
啦啦,我是run函数
run
4
啦啦,我是run函数
run
5
啦啦,我是run函数
run
6
啦啦,我是run函数
run
7
啦啦,我是run函数
run

代码02:

# coding=utf-8
from functools import update_wrapper
nums = [1, 2, 3, 4, 5, 6]


def run(num):
    """啦啦,我是run函数"""
    num += 1
    print num


def test():
    "哈哈,我是test函数"
    for num in nums:
        def func():
            "呵呵,我是func函数"
            return run(num)
        update_wrapper(func, run)
        test.__doc__ = str(num) + 'doc'
        test.__name__ = str(num) + 'name'
        # func.description = 'desc'
        # print func.description
        # func.hehe = 'desc'
        # print func.hehe
        yield func


if __name__ == "__main__":
    for f in test():
        print '*'*10
        f()
        # print f.__doc__
        # print f.__name__
        print test.__doc__
        print test.__name__

输出02:

**********
2
1doc
1name
**********
3
2doc
2name
**********
4
3doc
3name
**********
5
4doc
4name
**********
6
5doc
5name
**********
7
6doc
6name

 

 

<think>好的,我现在需要回答用户关于Pythonfunctools模块的功能和用途的问题。首先,我需要回忆一下functools模块的主要功能,并结合用户提供的引用资料来组织回答。 用户提供的引用中提到了几个关键点:函数缓存(lru_cache)、函数装饰器(wraps、update_wrapper)、参数固定(partial)、函数比较(cmp_to_key)等。我需要确保涵盖这些内容,并结构清晰地分点说明。 首先,我应该介绍functools模块的整体作用,作为函数式编程的工具箱,提供高阶函数处理工具。然后,分点详细说明每个常见功能,比如函数缓存中的lru_cache,参数固定中的partial,装饰器处理中的wraps,函数比较中的cmp_to_key,以及reduce函数。每个部分需要给出示例代码,这样用户能更直观地理解用法。 在写代码示例时,需要注意使用正确的格式,行内公式用$...$,独立公式用$$...$$,但在这个回答中可能公式较少,主要关注代码块。同时,要确保引用正确,比如在提到lru_cache时,引用对应的引用编号[^1]或[^2]。 还要注意用户提到的引用中的内容,比如引用[4]提到update_wrapper和wraps用于消除装饰器的副作用,这点需要在装饰器处理部分详细说明。同时,引用[3]强调functools作为高阶函数处理工具,可以组合和修改函数,这也是模块的核心作用。 此外,用户要求生成相关问题,我需要根据内容提出几个相关的问题,比如lru_cache的应用场景、partial的用法比较、装饰器保留元信息的方法等。 最后,检查回答是否符合结构要求:先介绍模块作用,再分点详细说明每个功能,每个功能下给出代码示例,并正确添加引用标记。然后列出相关问题,确保问题与内容相关,帮助用户深入学习。 现在开始组织内容,确保每个部分清晰,代码示例正确,引用标记自然添加,避免遗漏重要功能点。</think>### Python functools模块详解 `functools` 是 Python 标准库中专门用于高阶函数(处理或返回其他函数的函数)的模块,它为函数式编程提供了核心工具。以下是其核心功能及常见用法: --- #### 一、函数缓存(优化性能) 1. **`lru_cache`** 通过缓存函数调用的结果减少重复计算,特别适合递归或计算密集型函数。 ```python from functools import lru_cache @lru_cache(maxsize=128) def fibonacci(n): if n < 2: return n return fibonacci(n-1) + fibonacci(n-2) ``` - `maxsize`:指定缓存大小,默认 128,设为 `None` 表示无限制[^1]。 - `typed`:若为 `True`,不同参数类型的调用会分开缓存(如 `1` 和 `1.0`)[^1]。 --- #### 二、参数固定(简化函数调用) 2. **`partial`** 固定函数的部分参数,生成新函数以减少重复输入: ```python from functools import partial def power(base, exponent): return base ** exponent square = partial(power, exponent=2) print(square(3)) # 输出 9 ``` --- #### 三、装饰器处理(保留元信息) 3. **`wraps`** 解决装饰器覆盖原函数元信息(如名称、文档)的问题: ```python from functools import wraps def log(func): @wraps(func) def wrapper(*args, **kwargs): print(f"调用函数: {func.__name__}") return func(*args, **kwargs) return wrapper @log def add(x, y): """加法函数""" return x + y print(add.__name__) # 输出 "add",而非 "wrapper" print(add.__doc__) # 输出 "加法函数" ``` 原理是通过 `WRAPPER_ASSIGNMENTS` 和 `WRAPPER_UPDATES` 复制原函数属性[^4]。 --- #### 四、函数比较与排序 4. **`cmp_to_key`** 将旧式比较函数转换为新式键函数,兼容 Python 3 的排序方法: ```python from functools import cmp_to_key def compare(a, b): if a % 2 == b % 2: return a - b return -1 if a % 2 == 1 else 1 sorted_nums = sorted([3, 1, 4, 2], key=cmp_to_key(compare)) print(sorted_nums) # 输出 [1, 3, 2, 4](奇数在前,同奇偶则升序) ``` --- #### 五、其他工具函数 5. **`reduce`** 对序列元素进行累积操作(需导入): ```python from functools import reduce product = reduce(lambda x, y: x * y, [1, 2, 3, 4]) # 输出 24 ``` --- #### 六、方法装饰器(面向对象) 6. **`singledispatch`** 实现函数重载,根据参数类型选择不同实现: ```python from functools import singledispatch @singledispatch def process(data): raise NotImplementedError @process.register(str) def _(data): return f"处理字符串: {data.upper()}" @process.register(int) def _(data): return f"处理整数: {data * 2}" print(process("hello")) # 处理字符串: HELLO print(process(5)) # 处理整数: 10 ``` --- ###
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值