如何在Python中从字符串列表批量创建带指定命名空间标签的def定义函数
如何在Python中从字符串列表批量创建带指定命名空间标签的def定义函数
嘿,这个需求我之前也碰到过,批量生成对应名字的函数确实能省不少重复写代码的功夫。其实思路和你提到的lambda方式类似——都是靠操作Python的命名空间字典来实现,只不过这次我们用def来定义函数对象,再把它们绑定到指定的名字上。
先给你直接上可行的代码方案,再慢慢拆解细节:
方案一:绑定到全局命名空间
如果你确实需要把这些函数放到全局命名空间里(就像手动写def label1()那样),可以这么做:
exampleList = ['label1', 'label2', 'label3', 'label4'] for idx, func_name in enumerate(exampleList): # 注意这里要把idx作为默认参数传入,避免闭包延迟绑定的坑 def func(arg: str, idx=idx): target_word = exampleList[idx] if len(arg) > len(target_word): print(f"the word {arg} has more letters than the word {target_word}") # 将函数对象绑定到全局命名空间的对应名字上 globals()[func_name] = func
测试一下效果:
label1("helloworld") # 输出:the word helloworld has more letters than the word label1 label2("test") # 因为"test"长度4 < "label2"的6,所以无输出
关键细节:闭包的坑
这里必须提一下为什么要加idx=idx这个默认参数:Python的闭包是延迟绑定的,如果直接在函数里用idx,所有生成的函数都会引用循环结束后的最后一个idx值(也就是3,对应label4)。把idx作为默认参数传入后,每个函数都会在定义时捕获当前的idx值,这样每个函数才会对应正确的列表元素。
如果担心后续exampleList被修改导致函数逻辑出错,还可以直接把目标字符串捕获到函数里,更安全:
for idx, func_name in enumerate(exampleList): target_word = exampleList[idx] def func(arg: str, target=target_word): if len(arg) > len(target): print(f"the word {arg} has more letters than the word {target}") globals()[func_name] = func
方案二:用字典存储函数(更推荐)
如果不是必须要把函数放到全局命名空间里,我更推荐用一个字典来存储这些函数,这样不会污染全局变量,也更便于管理:
exampleList = ['label1', 'label2', 'label3', 'label4'] func_collection = {} for idx, func_name in enumerate(exampleList): target_word = exampleList[idx] def func(arg: str, target=target_word): if len(arg) > len(target): print(f"the word {arg} has more letters than the word {target}") func_collection[func_name] = func # 使用的时候直接通过字典调用 func_collection['label1']("helloworld")
原理说明
其实Python的命名空间本质上就是字典:globals()返回全局命名空间的字典,locals()返回当前局部作用域的字典。当你手动写def label1(): ...时,Python本质上就是在当前命名空间的字典里添加了一个键值对——键是label1,值是这个函数对象。我们批量创建函数,就是手动完成这个键值对的绑定过程而已。
备注:内容来源于stack exchange,提问作者YikesItsSykes
相关产品推荐
相关产品推荐

