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

《流畅的Python》读书笔记08(补充01): 函数是一等对象函数式编程核心(简洁版)

对“函数作为一等对象”这一编程范式的实现与应用上,其核心并非单一算法,而是一套以高阶函数为核心、支持函数式编程风格的函数操作与组合机制。本文将对该机制进行深度拆解。

一、 核心逻辑框架:一等函数与高阶函数

博客的核心逻辑建立在两个相互关联的概念上:一等函数(First-Class Function)与高阶函数(Higher-Order Function)。

  • 一等函数:指函数在语言中享有与基础数据类型(如整数、字符串)同等的地位。这具体表征为函数可被赋值给变量、作为参数传递、作为返回值从其他函数中返回,并能存储在数据结构中。博客通过factorial函数的赋值(fact = factorial)、作为map函数的参数传递等操作,直观演示了此特性。
  • 高阶函数:是指以函数为参数或返回函数的函数。这是一等函数特性的直接应用,构成了函数式编程风格的基础。map,filter,sorted等内置函数是典型的高阶函数。

二、 核心逻辑的深度拆解

该机制可拆解为以下四个层次:

1. 数据抽象层:函数作为可操作的数据单元

此层实现了函数到数据的抽象映射。

  • 实现方式:Python 解释器将deflambda定义的函数编译为一个function类的实例对象。该对象拥有__call__方法使其可调用,同时拥有__name____doc____code__等一系列属性,可通过dir()进行内省。
  • 关键操作
    • 赋值func_alias = original_func。这实质上是将函数对象的引用复制给新变量。
    • 数据结构存储:可将函数作为值存入列表、字典等。博客中operations = {'+': add, '-': sub, '*': mul}是策略模式的经典实现。
    • 作为参数与返回值:这是实现回调、装饰器等模式的基础。
2. 运算组合层:高阶函数与函数组合

此层定义了如何对“函数数据”进行运算和组合,以实现复杂的逻辑。

  • 核心高阶函数及其逻辑

    高阶函数输入核心算法逻辑输出/效果
    map(func, iterable)一个函数func,一个可迭代对象iterable遍历iterable,将每个元素e应用func(e),并惰性生成结果。一个新的迭代器,包含转换后的元素。
    filter(func, iterable)一个返回布尔值的函数func,一个可迭代对象iterable遍历iterable,仅当func(e)True时,惰性生成该元素e一个新的迭代器,包含满足条件的元素。
    sorted(iterable, key=None)一个可迭代对象iterable,一个可选的关键字函数key使用 Timsort 算法排序。若提供key,则在比较前对每个元素应用key(e)函数,根据返回的键进行排序。一个新的已排序列表。
    functools.reduce(func, iterable[, initial])一个接收两个参数的函数func,一个可迭代对象iterable,一个可选的初始值initial1. 若提供initial,则累积器accumulator初始化为initial,否则取iterable的第一个元素。
    2. 遍历iterable的剩余元素,执行accumulator = func(accumulator, element)
    3. 返回最终的accumulator
    将序列归约为单个值。
  • 逻辑示例:使用sorted与自定义key函数

    fruits = ['strawberry', 'fig', 'apple', 'cherry', 'raspberry', 'banana'] # 关键逻辑:sorted函数内部会为每个元素调用key函数,用其返回值作为排序依据 def reverse(word): return word[::-1] # 返回字符串的逆序 sorted_fruits = sorted(fruits, key=reverse) # 排序过程(概念性): # 1. 为每个水果生成键:reverse('strawberry') -> 'yrrebwarts', reverse('fig') -> 'gif', ... # 2. 根据键 'yrrebwarts', 'gif', ... 进行字母排序。 # 3. 按排序后的键的顺序,返回对应的原始元素。 print(sorted_fruits) # 输出: ['banana', 'apple', 'fig', 'raspberry', 'strawberry', 'cherry']
3. 语法简化层:匿名函数与推导式

此层提供了更简洁的语法来表达高阶函数的逻辑。

  • Lambda 表达式:用于定义简单的匿名函数,通常作为高阶函数的参数。其逻辑等价于一个单表达式的def函数,但语法更紧凑。
    # 使用lambda替代具名函数reverse sorted_fruits_lambda = sorted(fruits, key=lambda word: word[::-1])
  • 列表推导式与生成器表达式:提供了比mapfilter更符合 Python 习惯的、可读性更高的替代方案,尤其当逻辑包含条件过滤时。
    # 使用map和filter result_map_filter = list(map(factorial, filter(lambda n: n % 2, range(6)))) # 使用列表推导式(逻辑更清晰) result_comprehension = [factorial(n) for n in range(6) if n % 2]
4. 扩展协议层:可调用对象

此层允许非函数对象通过实现__call__方法获得函数的行为,从而融入高阶函数的生态系统。

  • 逻辑实现:任何定义了__call__(self, ...)方法的类,其实例都可以像函数一样被调用。callable()内置函数用于检测对象是否可调用。
    class Adder: def __init__(self, n): self.n = n # 保存状态 def __call__(self, x): return self.n + x # 定义调用时的行为 add_5 = Adder(5) # 实例化,状态 n=5 被保存 # 实例可像函数一样调用,逻辑是执行其 __call__ 方法 result = add_5(10) # 等价于 Adder.__call__(add_5, 10),返回 15
    这使得可以创建有状态的“函数对象”,在装饰器、闭包的替代实现等场景中非常有用。

三、 应用场景与范式

理解此核心逻辑后,可应用于多种范式:

  1. 策略模式:如博客所示,将不同的算法(函数)存储在字典中,运行时根据键动态选择并执行。
  2. 回调机制与事件驱动:将函数作为参数传递给其他函数,在特定条件满足时(如事件触发、异步操作完成)被调用。
  3. 装饰器:高阶函数返回函数的特例,用于透明地增强函数功能。
  4. 函数式编程风格:通过mapfilterreduce以及函数组合,编写无副作用、声明式的代码。
  5. 依赖注入与测试:可以轻松地将模拟函数(mock)作为参数传入,便于单元测试。

综上所述,博客内容的核心逻辑是一套以函数对象化为基础、以高阶函数组合为手段的编程范式。它通过将代码逻辑封装为可传递和操作的一等公民,极大地提升了程序的表达力、灵活性和模块化程度。从map/filter到列表推导,再到可调用对象,体现了 Python 在提供强大抽象能力的同时,也兼顾了代码的简洁与可读性。


参考来源

  • 《流畅的Python》读书笔记08: 第二部分 函数即对象 - 函数是一等对象
http://www.jsqmd.com/news/859539/

相关文章:

  • FPGA还是自研?聊聊5G RRU里DPD方案的选型与落地实战
  • 通过taotokencli工具一键配置团队开发环境中的大模型api密钥
  • 3分钟零成本解锁Microsoft 365全功能:Ohook开源方案实战指南
  • 企业微信API自动化:如何实现稳定高效的私域
  • 从仿真到原理:用Multisim14.0复现Buck电路,我搞懂了CCM模式下的电压电流波形
  • 2026电话客服系统AI大模型解决方案选择清单:3个核心参考要点 - 资讯速览
  • 收藏 | 大模型岗位全解析:面试5类岗位后,我发现它们竟然是5种工作!小白程序员必看
  • 基于i.MX8M Mini核心板的工业压力位移智能分析仪方案详解
  • 如何快速使用League Akari:英雄联盟玩家的终极效率工具指南
  • EPLAN 2022里给PLC元件和IO点加注释,记住这3个位置就够了(附竖向文字技巧)
  • Taotoken API Key管理与审计日志功能在团队协作中的价值
  • 如何用KaTrain围棋AI训练系统快速提升棋艺水平?
  • OpenAvatarChat终极指南:5步搭建属于你的AI数字人对话系统
  • 国产SiC MOSFET在LLC与移相全桥电源中的实战优势与设计要点
  • Python websocket-client事件回调全解析:从连接到关闭,一个不漏的保姆级指南
  • Taotoken用量看板如何帮助团队清晰管理API调用成本
  • WarcraftHelper终极指南:让经典魔兽3在现代电脑上焕发新生
  • 告别轮询!用STM32 HAL库+TM1638实现高效按键扫描与事件处理
  • 避坑指南:在Ubuntu 20.04上从零配置华为昇腾MindX SDK与CANN 5.0.2的完整流程
  • 如何用NotaGen在10分钟内实现AI古典音乐生成:完整教程与实战指南
  • 深度探索ChromePass:掌握浏览器密码管理的核心技术
  • 企业跨境直播环境里,专线和带宽到底该怎么分配?
  • 从开关到放大器:手把手用MOSFET小信号模型分析一个共源极放大电路
  • 从‘探索启动’到‘ε-贪心’:蒙特卡洛强化学习在真实业务场景下的演进与选型思考
  • 仅剩最后47个名额|ElevenLabs福建话语音定制服务内部通道开放:含福州话/闽南语双轨音色备案及司法存证支持
  • PrismLauncher-Cracked:打破网络束缚,解锁Minecraft离线启动新体验
  • 独立开发者如何利用Taotoken构建多模型支持的AI小产品
  • 【ElevenLabs甘肃话语音落地实战指南】:20年AI语音工程师亲授方言适配3大避坑法则与本地化部署全流程
  • 观察使用Taotoken后月度AIAPI账单变得清晰可预测的过程
  • 别光看手册了!手把手教你用STM32CubeMX + HAL库快速点亮STM32F429的第一盏灯