柯里化和闭包协同实现过滤逻辑的可装配性:闭包封存预设参数(如字段、阈值),柯里化分步固化参数,生成可复用、可组合的单参数过滤函数。

柯里化和闭包不是炫技工具,而是让过滤逻辑真正“可装配”的底层支撑。核心思路是:把过滤条件拆成可预设的参数,再用闭包封存状态,最终产出一个随时能接数据流的函数。
先理解它们怎么协同工作
闭包负责“记住”你设定的规则(比如阈值、字段名、匹配模式),柯里化负责把多参数过滤函数逐步收窄为单参数调用形式。两者结合,就能从 filter_by(field, value, op) 变成 filter_by_field('price')(50)('gt') 这类链式、可复用的算子。
- 闭包保留外部变量(如
threshold=100),让内部函数每次调用都基于同一上下文 - 柯里化把
lambda item: item['score'] > threshold这种硬编码逻辑,变成可配置的make_gt_filter('score', 100) - 二者叠加后,同一个过滤函数可以生成多个定制版本,互不干扰
手把手写一个通用数值比较过滤器
以“字段大于某值”为例,不用写死字段名或数字:
def make_comparator(field, threshold):
def compare(item):
return item.get(field, 0) > threshold
return compare
<h1>柯里化改造:支持分步传参</h1><p>def curry_filter(field):
def by_threshold(threshold):
def apply_to(item):
return item.get(field, 0) > threshold
return apply_to
return by_threshold</p><h1>使用示例</h1><p>filter_price_gt = curry_filter('price')(80)
data = [{'price': 95}, {'price': 60}, {'price': 120}]
list(filter(filter_price_gt, data)) # → [{'price': 95}, {'price': 120}]
这里 curry_filter('price') 返回一个闭包,它记住了 field;(80) 再返回另一个闭包,记住了 threshold;最后得到的函数才是真正的过滤器。
用 functools.partial 简化常见绑定场景
对固定操作符或字段的场景,partial 更轻量,本质也是闭包实现:
- 固定字段 + 固定操作:
from functools import partialis_expensive = partial(lambda item, limit: item['cost'] > limit, limit=200) - 固定操作符 + 动态字段:
gt_on = partial(lambda field, val, item: item.get(field, 0) > val, 'score')
调用时只需gt_on(85)(item) - 组合使用:
filter_by_score_gt_85 = partial(filter, gt_on(85)),直接获得可传入列表的过滤器
扩展成支持多条件的复合过滤器
真正高复用的过滤算子,要能自由拼装。利用闭包封装每个条件,再用逻辑组合:
def and_filter(*conditions):
def combined(item):
return all(cond(item) for cond in conditions)
return combined
<h1>构建两个独立闭包</h1><p>has_stock = lambda item: item.get('stock', 0) > 0
in_budget = curry_filter('price')(150)</p><h1>组合成新算子</h1><p>affordable_in_stock = and_filter(has_stock, in_budget)
list(filter(affordable_in_stock, items))
每个条件都是独立闭包,可单独测试、复用、缓存,也能任意组合——这才是“自由组合”的实质。
不复杂但容易忽略:关键不在语法多漂亮,而在每次封装时是否明确“什么该变、什么该固定”。把变的部分留给调用时传,不变的部分用闭包锁住,柯里化只是让这个过程更自然。

















