如何获取捕获变量的Lambda表达式源码(含具体捕获值)
获取Lambda函数捕获的闭包变量并生成替换后的源码
解决方案思路
Lambda函数的闭包变量存储在__closure__属性中,结合inspect.getsource获取的原始源码,将变量名替换为实际捕获的值即可得到目标源码。
具体实现代码
1. 基础实现(针对单个闭包变量)
import re from inspect import getsource def make_func(pattern = "black.*"): func = lambda x: re.fullmatch(pattern, x) return func # 生成带指定pattern的Lambda函数 target_func = make_func("white.*") # 提取捕获的pattern值 captured_pattern = target_func.__closure__[0].cell_contents # 转义字符串中的双引号,避免生成的源码语法错误 escaped_pattern = captured_pattern.replace('"', '\\"') # 获取Lambda的原始源码 raw_source = getsource(target_func).strip() # 替换变量为实际值 final_source = raw_source.replace("pattern", f'"{escaped_pattern}"') print(final_source) # 输出:func = lambda x: re.fullmatch("white.*", x)
2. 通用实现(支持多个闭包变量)
如果Lambda捕获了多个变量,通过__code__.co_freevars获取变量名列表,与__closure__中的值一一对应,批量替换:
import re from inspect import getsource def make_func(pattern = "black.*", flags=0): func = lambda x: re.fullmatch(pattern, x, flags=flags) return func target_func = make_func("test.*", re.IGNORECASE) # 构建变量名与捕获值的映射 free_vars = target_func.__code__.co_freevars closure_values = [cell.cell_contents for cell in target_func.__closure__] var_mapping = dict(zip(free_vars, closure_values)) raw_source = getsource(target_func).strip() final_source = raw_source for var_name, val in var_mapping.items(): # 针对字符串类型的值转义引号,非字符串直接转成字符串 if isinstance(val, str): escaped_val = val.replace('"', '\\"') final_source = final_source.replace(var_name, f'"{escaped_val}"') else: final_source = final_source.replace(var_name, str(val)) print(final_source) # 输出:func = lambda x: re.fullmatch("test.*", x, flags=2)
关键说明
inspect.getsource是从源文件中读取代码文本,不会替换运行时绑定的闭包变量,因此需要手动替换。__closure__属性存储Lambda捕获的外部变量,每个元素是cell对象,cell_contents属性为变量的实际值。__code__.co_freevars返回Lambda捕获的外部变量名列表,顺序与__closure__中的元素一一对应。
内容的提问来源于stack exchange,提问作者not_a_robot
相关产品推荐
相关产品推荐

