当前位置: 首页 > news >正文

python 标准库之 functools 模块

functools 模块提供了一系列用于处理函数的工具。其中,像 partial 可以创建一个新的可调用对象,这个对象固定了原函数的部分参数,有点像给函数穿上了“参数防护服”;reduce 能对一个序列进行累积计算,就好比是一个勤劳的小会计,按顺序把序列里的数加起来或者做其他运算;wraps 主要用于装饰器,它能帮助装饰器函数保留被装饰函数的元信息,比如函数名、文档字符串等,让被装饰函数“表里如一”。

底层原理

  1. partialpartial 创建新对象的原理是,它会创建一个新的函数对象,这个新函数内部持有原函数的引用,并且记录下固定的参数。当调用新函数时,它会把新传入的参数和之前固定的参数合并起来,一起传递给原函数进行调用。
  2. reduce:在 Python 3 里,reduce 已经从全局命名空间移到了 functools 模块中。它的底层实现是通过迭代序列,不断地将当前的计算结果和序列中的下一个元素作为参数传递给指定的函数,持续进行累积计算,直到序列遍历完,最终返回累积的结果。
  3. wrapswraps 本质上是一个装饰器,它会将被装饰函数(也就是原函数)的一些属性,如 __name____doc__ 等,复制到装饰器函数中。这样在使用装饰器后,被装饰函数在外部看起来就像是没有被装饰过一样,保留了原有的标识和文档说明。

细节

  1. partial:使用 partial 固定参数时,要注意参数的顺序。如果原函数有位置参数和关键字参数,固定位置参数时要按照原函数定义的顺序来。另外,新创建的函数对象的 __name__ 属性默认是原函数名加上 partial,可以通过手动修改来让它更符合你的需求。
  2. reducereduce 的第一个参数是一个二元函数(即接受两个参数的函数),如果序列为空,且没有提供初始值,会抛出 TypeError。而当提供了初始值时,reduce 会从初始值开始计算,即使序列为空也能正常返回初始值。
  3. wraps:在自定义装饰器时,如果不使用 wraps,可能会导致一些工具(如 help() 函数)在查看被装饰函数的文档时出现错误,因为函数的元信息已经被装饰器函数覆盖了。所以,为了保持函数的完整性和可读性,使用 wraps 是个好习惯。

使用方式

  1. partial:假设有一个计算两数之和的函数,现在想固定其中一个参数。
import functools


def add(a, b):
    return a + b


add_five = functools.partial(add, 5)
result = add_five(3)
print(result)
  1. reduce:计算列表中所有数字的乘积。
import functools


def multiply(x, y):
    return x * y


nums = [2, 3, 4]
product = functools.reduce(multiply, nums)
print(product)
  1. wraps:创建一个简单的装饰器,并使用 wraps 保留原函数信息。
import functools


def my_decorator(func):
    @functools.wraps(func)
    def wrapper(*args, **kwargs):
        print("Before function call")
        result = func(*args, **kwargs)
        print("After function call")
        return result

    return wrapper


@my_decorator
def greet(name):
    """这个函数用于打招呼"""
    return f"Hello, {name}!"


print(greet.__name__)
print(greet.__doc__)

场景训练

  1. 表单验证场景:假设有一个验证,函数用于验证输入是否在指定范围内,现在要针对不同的范围创建多个验证函数。
import functools


def validate_in_range(min_val, max_val, value):
    return min_val <= value <= max_val


validate_1_to_100 = functools.partial(validate_in_range, 1, 100)
is_valid = validate_1_to_100(50)
print(is_valid)
  1. 数据聚合场景:在处理一组学生成绩时,计算所有成绩的平均值。
import functools


def sum_scores(acc, score):
    return acc + score


scores = [85, 90, 78]
total = functools.reduce(sum_scores, scores, 0)
average = total / len(scores)
print(average)
  1. 日志记录场景:创建一个装饰器,在函数执行前后记录日志,并保留原函数信息。
import functools
import logging


def log_decorator(func):
    @functools.wraps(func)
    def wrapper(*args, **kwargs):
        logging.info(f"开始执行函数 {func.__name__}")
        result = func(*args, **kwargs)
        logging.info(f"函数 {func.__name__} 执行结束")
        return result

    return wrapper


@log_decorator
def process_data(data):
    """处理数据的函数"""
    return data * 2


print(process_data.__name__)
print(process_data.__doc__)

代码实践

# partial 代码实践
import functools


def power(base, exponent):
    return base ** exponent


square = functools.partial(power, exponent=2)
num = 5
squared_num = square(num)
print(f"{num} 的平方是: {squared_num}")

# reduce 代码实践
import functools


def concatenate_strings(str1, str2):
    return str1 + str2


strings = ['Hello, ', 'world!']
concatenated = functools.reduce(concatenate_strings, strings)
print("拼接后的字符串:", concatenated)

# wraps 代码实践
import functools


def timeit_decorator(func):
    @functools.wraps(func)
    def wrapper(*args, **kwargs):
        import time
        start_time = time.time()
        result = func(*args, **kwargs)
        end_time = time.time()
        print(f"{func.__name__} 执行时间: {end_time - start_time} 秒")
        return result

    return wrapper


@timeit_decorator
def slow_function():
    """模拟一个耗时操作"""
    import time
    time.sleep(2)
    return "操作完成"


print(slow_function.__name__)
print(slow_function.__doc__)
result = slow_function()
print(result)

相关文章:

  • 豪越科技:融合低空经济的消防一体化安全管控解决方案
  • openai agent实践
  • 什么是MCP|工作原理是什么|怎么使用MCP|图解MCP
  • 六十天前端强化训练之第二十七天之Pinia 状态管理全解与购物车实战案例
  • 【Linux】I/O 多路转接:select epoll 技术剖析
  • 安卓 vs iOS 文件系统深度解析:开放自由与封闭安全的终极博弈
  • DeepSeek 助力 Vue3 开发:打造丝滑的表格(Table)之添加导出数据功能示例10,TableView15_10带搜索的导出表格示例
  • [DDD架构]不同数据模型DTO、VO、PO、DAO、DO的含义
  • 自动驾驶系统的车辆动力学建模:自行车模型与汽车模型的对比分析
  • Linux:基础IO---文件描述符
  • JavaSE1.0(实战之图书管理系统)
  • FlowMo: 模式搜索+扩散模型提升图像Token化性能
  • 基于Azure Delta Lake和Databricks的安全数据共享(Delta Sharing)
  • C++异常处理完全指南:从原理到实战
  • 操作系统知识点33
  • 31天Python入门——第10天:深入理解值传递·引用传递以及深浅拷贝问题
  • 计算机网络性能优化相关内容详解
  • Bash语言的测试框架
  • 996引擎-接口测试:音效测试NPC
  • 数据结构—树(java实现)
  • 李在明回应韩国大法院判决:与自己所想截然不同,将顺从民意
  • 国铁集团去年收入12830亿元增3%,全年铁路运输利润总额创新高
  • 湖北鄂城:相继4所小学有学生腹泻呕吐,供餐企业负责人已被采取强制措施
  • “面具女孩”多次恐吓电梯内两幼童,当事女孩及家长道歉后获谅解
  • 济南高新区一季度GDP增长8.5%,第二产业增加值同比增长14.4%
  • “女乘客遭顺风车深夜丢高速服务区”续:滴滴永久封禁两名涉事司机账号