【JAVA工程师从0开始学AI】,第四步:闭包与高阶函数——用Python的“魔法函数“重构Java思维
副标题:当严谨的Java遇上"七十二变"的Python函数式编程
历经变量战争、语法迷雾、函数对决,此刻我们将踏入Python最迷人的领域——函数式编程。当Java工程师还在用接口和匿名类实现回调时,Python的闭包已化身"智能机器人",带着"记忆传承"的能力自由穿梭于代码之间。这里没有类的枷锁,函数既是武器又是盾牌,高阶函数组合出的"代码万花筒",正是AI数据处理、模型训练的核心密码。本文将用Java程序员熟悉的战场,揭开Python函数式编程的降维打击!
先来看一段Python的代码全貌【套娃函数】
def make_function(parity): # ① 母函数# 根据参数生成不同过滤规则if parity == 'even':matches_parity = lambda x: x % 2 == 0 # ② 小工具Aelif parity == 'odd':matches_parity = lambda x: x % 2 != 0 # 小工具Belse:raise AttributeError("参数不对!") # ③ 防呆设计# 核心功能藏在子函数里def get_by_parity(numbers): # ④ 子函数return [num for num in numbers if matches_parity(num)] # 关键魔法在这里return get_by_parity # ⑤ 把子函数当礼物送出去
下面逐行解析,上面每一行Python代码是什么意思
① 母函数开工
make_function('odd')被调用时,就像开了一家定制化工厂- 参数
parity是订单要求(要奇数还是偶数过滤器)
② 流水线选择
if parity == 'even':matches_parity = lambda x: x%2 ==0 # 造偶数检测器
elif parity == 'odd':matches_parity = lambda x: x%2 !=0 # 造奇数检测器
- 根据订单选择生产线(
lambda就是迷你检测装置) - 相当于给后续流程安装不同的"筛子"
③ 容错机制
else:raise AttributeError("Unknown Parity: "+parity)
- 防止乱传参数(比如传了个"cat"进来)
- 相当于工厂质检员,发现不合格订单直接拒收
④ 核心生产线
def get_by_parity(numbers):return [num for num in numbers if matches_parity(num)]
- 这才是真正干活的流水线
matches_parity这个筛子是从母函数拿的(重点!)- 列表推导式就像传送带,逐个检查数字
⑤ 出厂发货
return get_by_parity
- 不返回具体产品,而是返回整条定制化流水线
- 相当于客户拿到的是专属生产机器
闭包魔法揭秘(重点难点)
当执行 get_odds = make_function('odd') 时:
- 母函数执行完毕,按理说内部变量该销毁了
- 但是子函数
get_by_parity记住了当时创建的matches_parity - 就像时间胶囊,把当时的判断条件冻结保存了
Java对比时刻(用你熟悉的领域):
// Java 实现类似闭包(需要用到接口)
interface NumberChecker {boolean check(int x);
}public static NumberChecker makeChecker(String parity) {
if ("odd".equals(parity)) {return x -> x % 2 != 0; // lambda表达式
} else {return x -> x % 2 == 0;
}
}
// 使用时:
NumberChecker oddChecker = makeChecker("odd");
oddChecker.check(5); // true
- Python的闭包更简洁,不用显式定义接口
- Java8的lambda确实和Python的闭包更相似了
实战演示(眼见为实)
# 下单定制奇数过滤器
get_odds = make_function('odd') # 拿到专属流水线# 来料加工
print(get_odds(range(10))) # [1,3,5,7,9] # 再下单一台偶数过滤器
get_evens = make_function('even')
print(get_evens([2,5,8,11])) # [2,8]
关键理解点:
get_odds不是数据,而是一个功能完整的函数- 每次调用
make_function都像开新工厂,生产不同型号的机器
设计哲学(作者想传达的)
- 函数是一等公民:可以当参数传递、当返回值、存在变量里
- 闭包的力量:子函数能记住出生时的环境(母函数的变量)
- Python特色:相比Java的面向对象思维,这里用纯函数式解决更简洁
举个反例(如果用Java思维写Python):
class ParityFilter: # 强行用类实现def __init__(self, parity):self.parity = paritydef filter(self, numbers):if self.parity == 'odd':return [x for x in numbers if x%2 !=0]else:return [x for x in numbers if x%2 ==0]# 使用对比
get_odds = ParityFilter('odd').filter # 类版
vs
get_odds = make_function('odd') # 函数版
- 函数式版本更轻量,不需要定义类
- 符合"能用简单结构就不用复杂封装"的Python哲学
来自Java程序员的灵魂拷问!
如果你作为一个Java程序员,经历过上面的代码,可能就会像我当时学的这段内容的时候,发出灵魂的拷问。
灵魂拷问:这个方法感觉像 “脱裤子放屁”,为什么不把参数一次给全了,然后直接根据判断返回结果?
回答:其实这正是Python的精妙支持也正是理解高阶函数的关键所在。我来用「点外卖」的比喻帮你彻底搞懂这种写法的精妙之处:
场景对比(直接传参 vs 工厂函数)
方案A:每次点单都说明要求(直接传参)
def 做奶茶(原料, 温度, 甜度):if 温度 == '去冰': 处理温度()if 甜度 == '三分糖': 调整甜度()return 成品# 每次点单都要重复说要求
做奶茶(原料, '去冰', '三分糖')
做奶茶(原料, '去冰', '三分糖')
做奶茶(原料, '去冰', '三分糖')
方案B:先定制个人菜单(工厂函数)
def 奶茶工厂(温度, 甜度):def 我的专属奶茶(原料):if 温度 == '去冰': 处理温度()if 甜度 == '三分糖': 调整甜度()return 成品return 我的专属奶茶# 一次设定,终身受用
我的奶茶 = 奶茶工厂('去冰', '三分糖')
我的奶茶(原料)
我的奶茶(原料)
我的奶茶(原料)
为什么方案B更优雅?
- 避免重复劳动(DRY原则)
-
- 就像把常用地址存到外卖APP里,不用每次手动输入
- 在需要多次调用相同配置时,节省大量重复参数
- 关注点分离
-
- 配置阶段:专注设定规则(是奇数还是偶数)
- 执行阶段:专注处理数据(传数字列表就行)
- 函数即服务
# 把功能当乐高积木传递
data_pipeline = [make_function('even'), # 第一道过滤lambda x: [n for n in x if n>5], # 第二道过滤str # 第三道转换
]result = data
for processor in data_pipeline:result = processor(result)
- 延迟执行
-
- 像预先设置好参数的定时任务
- 真正执行的时机可以灵活控制
- 防御性编程
# 在配置阶段就排除错误
try:faulty_filter = make_function('invalid') # 立刻报错
except AttributeError:print("立刻发现配置错误")# 对比直接传参可能在运行时才报错
filter_numbers([1,2,3], 'invalid') # 可能到很晚才出错
实战场景案例
假设我们要处理电商订单:
def 创建订单过滤器(最低金额, 商品类别):def 实际过滤器(订单列表):return [订单 for 订单 in 订单列表if 订单.金额 >= 最低金额and 订单.类别 == 商品类别]return 实际过滤器# 在系统初始化时配置
过滤高价数码订单 = 创建订单过滤器(5000, '数码产品')
过滤食品订单 = 创建订单过滤器(0, '食品')# 在数据处理时直接使用
今日订单 = 获取今日订单()
重点客户订单 = 过滤高价数码订单(今日订单)
促销订单 = 过滤食品订单(今日订单)
什么时候该用这种模式?
| 场景特征 | 适用工厂函数 | 适合直接传参 |
| 需要重复使用相同配置 | ✅ | ❌ |
| 参数需要动态组合 | ✅ | ❌ |
| 配置需要在不同模块间传递 | ✅ | ❌ |
| 只需要单次使用 | ❌ | ✅ |
| 参数组合简单且不变化 | ❌ | ✅ |
回到你的例子(终极解密)
你设想的直接传参版本:
def 直接过滤(numbers, parity):if parity == 'odd':return [x for x in numbers if x%2 !=0]else:return [x for x in numbers if x%2 ==0]
VS 对比一下原文的工厂函数版本:
核心区别在于:当你在一个业务流程中需要多次使用同一种过滤规则时,比如:
# 在数据预处理流程中
数据流 = [原始数据1, 原始数据2, 原始数据3]# 如果用直接传参
清洗后数据 = [直接过滤(数据, 'odd') for 数据 in 数据流
]# 如果用工厂函数
奇数过滤器 = make_function('odd')
清洗后数据 = [奇数过滤器(数据) for 数据 in 数据流]
虽然在这个简单例子中差异不大,但当:
- 过滤逻辑更复杂时(比如需要10个参数)
- 需要跨多个函数传递过滤逻辑时
- 要动态生成不同过滤组合时
工厂函数的优势就会像滚雪球一样越来越大!
最后用一句话总结:这种模式就像函数界的3D打印机——先造模具(工厂函数),然后无限复制成品(闭包函数),比每次手工捏泥人(直接传参)高效得多!
有问题可以发邮件给我:leeborn@qq.com
相关文章:
【JAVA工程师从0开始学AI】,第四步:闭包与高阶函数——用Python的“魔法函数“重构Java思维
副标题:当严谨的Java遇上"七十二变"的Python函数式编程 历经变量战争、语法迷雾、函数对决,此刻我们将踏入Python最迷人的领域——函数式编程。当Java工程师还在用接口和匿名类实现回调时,Python的闭包已化身"智能机器人"…...
【R语言】回归分析与判别分析
一、线性回归分析 1、lm()函数 lm()函数是用于拟合线性模型(Linear Models)的主要函数。线性模型是一种统计方法,用于描述一个或多个自变量(预测变量、解释变量)与因变量(响应变量)之间的关系…...
AllData数据中台核心菜单十三:数据湖平台
🔥🔥 AllData大数据产品是可定义数据中台,以数据平台为底座,以数据中台为桥梁,以机器学习平台为中层框架,以大模型应用为上游产品,提供全链路数字化解决方案。 ✨奥零数据科技官网:…...
Spring Cloud Gateway中断言路由和过滤器的使用
一,Gateway概念 Spring Cloud Gateway(简称 Gateway)是一个基于 Spring WebFlux 的 API 网关解决方案,旨在为微服务架构中的客户端提供路由、负载均衡、认证、限流、监控等功能。它作为微服务架构中的流量入口,通常位…...
Android 13 上通过修改 AOSP 拦截 SystemUI 音量调节事件
定位关键代码SystemUI 的音量调节逻辑主要集中在以下类中: VolumeDialogController.java:负责与 AudioService 交互。 VolumeDialogImpl.java:处理 UI 交互事件(如按钮点击)。 PhoneWindowManager.java:处理物理按键事件(如音量键)。 拦截音量调节事件 以 VolumeDialog…...
AcWing 798. 差分矩阵
题目来源: 找不到页面 - AcWing 题目内容: 输入一个 n 行 m 列的整数矩阵,再输入 q 个操作,每个操作包含五个整数 x1,y1,x2,y2,c,其中 (x1,y1) 和 (x2,y2)表示一个子矩阵的左上角坐标和右下角坐标。 每个操作都要将…...
Docker 部署 MySQL 8 详细图文教程
🚀 作者主页: 有来技术 🔥 开源项目: youlai-mall ︱vue3-element-admin︱youlai-boot︱vue-uniapp-template 🌺 仓库主页: GitCode︱ Gitee ︱ Github 💖 欢迎点赞 👍 收藏 ⭐评论 …...
【Python】模式匹配 match语句详解(仅在Python 3.10及以上版本中可用)
文章目录 模式匹配 match语句(仅在 Python 3.10及以上版本 中可用)1. 基本语法2. 基本匹配操作2.1 匹配常量2.2 匹配变量2.3 匹配元组2.4 匹配列表2.5 匹配字典2.6 条件匹配 3. 应用场景 模式匹配 match语句(仅在 Python 3.10及以上版本 中可用) Python 3.10 及以上版本中才引…...
vscode ESP32配置
一、自定义文件组件使用xxxx.c xxxx.h 1: 控制端工程目录创建组件文件夹 》 idf.py -C components create-component User_led 2: 定义组件如果引用指定外部依赖库,当前文件的cmakelists.txt 添加 REQUIRES driver idf_component_register(SRCS "uesr_led.c"INCLU…...
idea 2019.3常用插件
idea 2019.3常用插件 文档 idea 2019.3常用插件idea 2023.3.7常用插件 idea 2019.3常用插件 插件名称插件版本说明1AceJump3.5.9AceJump允许您快速将插入符号导航到编辑器中可见的任何位置。只需按“ctrl;”,键入一个字符,然后在Ace Jump…...
全单模矩阵及其在分支定价算法中的应用
全单模矩阵及其在分支定价算法中的应用 目录 全单模矩阵的定义与特性全单模矩阵的判定方法全单模矩阵在优化中的核心价值分支定价算法与矩阵单模性的关系非全单模问题的挑战与系统解决方案总结与工程实践建议 1. 全单模矩阵的定义与特性 关键定义 单模矩阵(Unimo…...
算法与数据结构(最小栈)
题目 思路 为了返回栈中的最小元素,我们需要额外维护一个辅助栈 min_stack,它的作用是记录当前栈中的最小值。 min_stack的作用: min_stack的栈顶元素始终是当前栈 st 中的最小值。 每当st中压入一个新元素时,如果这个元素小于等…...
KVM设置端口转发
20250217 - 概述 在ubuntu下进行虚拟机开发环境设置,希望外网也能够进行访问, 一开始希望通过桥接的方式来实现,但是发现有些不适配;所以最后使用了 NAT转发的形式。 一开始看的文章[1],在设置路由转发之后…...
openCV中如何实现滤波
图像滤波用于去除噪声和图像平滑,OpenCV 提供了多种滤波器: 1.1. 均值滤波: import cv2# 读取图像 image cv2.imread("example.jpg")# 均值滤波 blurred_image cv2.blur(image, (5, 5)) # (5, 5) 是滤波核的大小 滤波核大小的…...
清影2.0(AI视频生成)技术浅析(二):自然语言处理
清影2.0(AI视频生成)中的自然语言处理(NLP)技术是其核心组件之一,负责将用户输入的自然语言文本转化为机器可以理解的语义表示,从而指导后续的视频生成过程。 一、基本原理 1. 目标 清影2.0的NLP技术旨在将用户输入的自然语言文本转化为机器可以理解的语义表示,从而指…...
五十天精通硬件设计第32天-S参数
系列文章传送门 50天精通硬件设计第一天-总体规划-CSDN博客 目录 1. S参数基础 2. S参数在信号完整性中的作用 3. 单端 vs. 差分S参数 4. S参数的关键特性 5. S参数的获取与使用 6. S参数分析中的常见问题 7. 实际案例:PCIe通道分析 8. 工具推荐 总结 信号完整性中…...
AI在网络安全中的应用:构建智能防护体系
AI在网络安全中的应用:构建智能防护体系 大家好,我是你们熟悉的人工智能与Python领域自媒体创作者Echo_Wish。今天我们来聊聊如何用AI技术提升网络安全水平。随着互联网的发展和数字化转型,网络安全威胁日益增多,传统的安全防护手段已经难以应对复杂多变的网络攻击。AI技术…...
【ISO 14229-1:2023 UDS诊断全量测试用例清单系列:第十七节】
ISO 14229-1:2023 UDS诊断服务测试用例全解析(InputOutputControl_0x2F服务) 作者:车端域控测试工程师 更新日期:2025年02月14日 关键词:UDS协议、0x2F服务、输入输出控制、ISO 14229-1:2023、ECU测试 一、服务功能概…...
2025 BabitMF 第一期开源有奖活动正式开启 !
为了促进开源社区的交流与成长,字节跳动开源的多媒体处理框架 BabitMF (GitHub - BabitMF/bmf: Cross-platform, customizable multimedia/video processing framework. With strong GPU acceleration, heterogeneous design, multi-language support, e…...
Docker 安装和配置 Nginx 详细图文教程
🚀 作者主页: 有来技术 🔥 开源项目: youlai-mall ︱vue3-element-admin︱youlai-boot︱vue-uniapp-template 🌺 仓库主页: GitCode︱ Gitee ︱ Github 💖 欢迎点赞 👍 收藏 ⭐评论 …...
链表和list
链表和list 算法题中的经典操作:用空间代替时间 双链表头插顺序: 1.先修改新结点的左右指针 2.然后修改结点y的左指针 3.最后修改哨兵位的右指针 双链表在任意位置(p)之后插入…...
深度学习机器学习:常用激活函数(activation function)详解
目录 Sigmoid Function ReLU(Rectified Linear Unit) LeakyReLU(Leaky Rectified Linear Unit) ClippedReLU(Clipped Rectified Linear Unit) PRelu(Parametric ReLU) Tanh&am…...
AIGC图生视频保姆级教程
一、AI文生图高阶技巧 推荐工具 ▸ MidJourney(艺术感最强) ▸ DALLE 3(与ChatGPT深度联动) ▸ Leonardo.ai(精细化参数控制) 核心策略 提示词架构: [主体描述][环境氛围][镜头语言][风格参数…...
【对比】Pandas 和 Polars 的区别
Pandas vs Polars 对比表 特性PandasPolars开发语言Python(Cython 实现核心部分)Rust(高性能系统编程语言)性能较慢,尤其在大数据集上(内存占用高,计算效率低)极快,利用…...
C# 鼠标点击ToolStripStatuslabel 在线修改Text属性并存储加载显示Text属性
在实际项目中为方便了解视觉软件的使用性,可能需要添加一些小而稍微实用的功能:一个StipStatus控件上的Label按钮属性Text需要修改并保存,软件重启后能够自动加载修改后的属性名。 定义变量 public static string controlsText System.Windows.Forms.A…...
下载安装运行测试开源vision-language-action(VLA)模型OpenVLA
1. 安装 项目官网OpenVLA 首先按照官网提示的以下代码,执行创建环境->安装最小依赖->git克隆项目等 # Create and activate conda environment conda create -n openvla python3.10 -y conda activate openvla# Install PyTorch. Below is a sample comma…...
PyQt6/PySide6 的 SQL 数据库操作(QtSql)
一、核心组件架构 1.1 QtSql模块构成 QSqlDatabase:数据库连接管理(支持连接池)QSqlQuery:SQL语句执行与结果遍历QSqlTableModel:可编辑的表格数据模型QSqlQueryModel:只读查询结果模型QSqlRelationalTab…...
【Zookeeper如何实现分布式锁?】
Zookeeper如何实现分布式锁? 一、ZooKeeper分布式锁的实现原理二、ZooKeeper分布式锁的实现流程三、示例代码四、总结一、ZooKeeper分布式锁的实现原理 ZooKeeper是一个开源的分布式协调服务,它提供了一个分布式文件系统的接口,可以用来存储和管理分布式系统的配置信息。 …...
【MySQL】环境变量配置
环境变量英文名SystemRoot,直译为“系统总(根)目录",主要指明操作系统的重要目录在哪里。那么配置MySQL的环境变量,就是在程序运行时,告诉操作系统你的MySQL目录位置。 复制MySQL安装目录:…...
为AI聊天工具添加一个知识系统 之103 详细设计之44 自性三藏 之4 祖传代码 之2
本文要点 要点 前面的所有讨论都是为了给出我的设计项目(为使用AI聊天工具的聊天者 开挂一个知识系统) 的祖传代码 的完整设计,其中 的“槽”(占位符变量)的 库元(宝性和自性creator -本俱 替换内容标准模…...
