函数居然能够当作“传家宝”? 高阶函数的秘密揭示: 将函数传来传去, 这才是处于高手的境界。

本文内容整理自道满高阶函数 - 道满

写代码最怕啥?逻辑重复写了N遍,就是抽不出来!

若告知你, 函数能够如同变量那般传来传去, 甚至还能“生产”函数, 你会相信吗?

这便是, 高阶函数(-order)。掌握了它, 你的代码抽象能力顿时提高一个层面水准, 可以编写出“工厂流水线”等级的灵活代码!

python 异步回调函数_Python高阶函数用法_函数作为参数返回值实例

一、什么是高阶函数?一句话:函数界的“高阶玩家”

依照教程原文来看, 高阶函数指的是这样的一类函数, 它们是能够去接收其他函数当作参数的函数, 同时也是能够将函数作为返回值的函数。

通俗理解:

这背后所依赖的是一个关键特性, 在其中, 函数属于“一等公民”, 教程中有这样的原话, 即这意味着函数能够如同其他的数据类型那样被传递以及使用。

二、函数是“一等公民”是啥意思?

1. 变量可以指向函数

# abs()是内置绝对值函数
print(abs(-10))  # 10
# 把函数本身赋值给变量
f = abs
print(f(-10))    # 10(f现在和abs一模一样)

2. 函数名本质也是变量

abs = 10  # 把abs指向了整数10
# abs(-10)  # 这行会报错!因为abs不再是函数了

教程给出提醒: 在实际去进行开发的时候, 是不建议对内置函数的引用做出修改的, 因为这么做会致使代码变得难以被理解, 以及难以进行维护。

三、函数作为参数:把“动作”传进去

这是高阶函数最常见的用法。教程给出了一个基础示例:

def add(x, y, f):
    """接收一个函数f作为参数,先把x和y分别交给f处理,再相加"""
    return f(x) + f(y)
print(add(-5, 6, abs))  # 输出:11(abs(-5)=5, abs(6)=6, 5+6=11)

实战案例:map() 函数

教程提到,“内置的map()函数是一个典型的高阶函数”:

numbers = [1, 2, 3, 4, 5]
squared = list(map(lambda x: x**2, numbers))
print(squared)  # [1, 4, 9, 16, 25]

map()所做之事为, 将一个函数, 此函数为求平方, 应用于列表的每一个元素之上。

四、函数作为返回值:生产函数的“工厂”

高阶函数不仅能“吃”函数,还能“生”函数。这叫闭包()。

教程示例:

def make_multiplier(factor):
    """返回一个乘法函数"""
    def multiplier(x):
        return x * factor
    return multiplier
double = make_multiplier(2)  # double是一个专门乘2的函数
triple = make_multiplier(3)  # triple是一个专门乘3的函数
print(double(5))  # 10
print(triple(5))  # 15

神奇的地方在于, 函数记住了外面的参数, 哪怕已经完成了执行, 是这样的情况。

五、装饰器:高阶函数的经典应用

教程指出,“装饰器是中高阶函数的典型应用”:

def logger(func):
    """记录函数调用的装饰器"""
    def wrapper(*args, **kwargs):
        print(f"正在调用 {func.__name__},参数:{args}, {kwargs}")
        return func(*args, **kwargs)
    return wrapper
@logger  # 这行等价于 add = logger(add)
def add(x, y):
    return x + y
print(add(3, 5))
# 输出:
# 正在调用 add,参数:(3, 5), {}
# 8

掌握装饰器, 以不改变原函数代码的方式, 为其“包裹”额外功能, 其底层是高阶函数在发挥作用!

六、现代高阶函数三板斧

教程介绍了 模块中的几个实用工具:

1. ():把列表归约为一个值

from functools import reduce
# 计算列表所有元素的乘积
product = reduce(lambda x, y: x * y, [1, 2, 3, 4])
print(product)  # 24(1*2*3*4)

2. ():固定函数的某些参数

from functools import partial
from operator import add
# 创建一个“加5”专用函数
add_five = partial(add, 5)
print(add_five(10))  # 15(5+10)
print(add_five(20))  # 25(5+20)

3. 类型注解(让高阶函数更规范)

from typing import Callable, TypeVar
T = TypeVar('T')
def apply_func(value: T, func: Callable[[T], T]) -> T:
    """把value交给func处理,然后返回结果"""
    return func(value)
result = apply_func(10, lambda x: x * 2)
print(result)  # 20

七、高阶函数 vs 普通函数(对比)八、最佳实践建议

教程给出了几条实用建议:

先说命名清晰这事儿, 要是高阶函数的参数设定成函数的话, 那就得用那种具备描述性质的名称, 像那种样子, 等等之类的。然后讲讲保持简洁这块, 高阶函数里头所蕴含的逻辑, 都应当争取做到尽可能地简单。再说说文档完善这方面, 得清晰明白地阐述表明参数函数的预期呈现出来的行为以及返回过来的值。最后聊聊考虑性能这块儿, 处在对性能有着较高敏感度的场景下, 得防止出现那些没有必要的函数调用。

最后总结

函数式编程的核心概念是高阶函数 根据教程进行总结 合理运用高阶函数能够。

一句话, 当你发觉多个函数仅仅存在“一小部分逻辑”存在差异时, 那就能够运用高阶函数将那一部分提取成为参数!

探讨谈论一下: 你曾使用过map, 亦或是装饰器吗, 有没有自行撰写过返回函数的高阶函数呢?

学习不走弯路!

体系化实战途径: 基础语法, 异步Web开发, 数据采集, 计算机视觉, NLP, 大模型RAG实战。

Logo

AtomGit 是由开放原子开源基金会联合 CSDN 等生态伙伴共同推出的新一代开源与人工智能协作平台。平台坚持“开放、中立、公益”的理念,把代码托管、模型共享、数据集托管、智能体开发体验和算力服务整合在一起,为开发者提供从开发、训练到部署的一站式体验。

更多推荐