我正在研究从数据动态生成Python类。(目的是让用户在不知道任何Python的情况下,在一个简单的文件中指定一些软件测试)。我遇到了意想不到的效果;作为一个玩具示例,可以快速检查是否可以根据命名方案创建方法,我做了以下工作:import unittestattrdict = {}for i in range(3): attrdict["test%s"%i]= types.MethodType(lambda self: i)attrdict["runTest"]=lambda self: [eval("self.test%s()"%i) for i in range(3)]dynTC = type('dynTC', (unittest.TestCase,), attrdict )现在当我执行dynTC().runTest()...我希望[0,1,2] 作为输出,但实际结果是[2,2,2]我希望lambda定义绑定循环索引的深层副本,因为它只是一个数字,而不是一个更复杂的结构,但是显然这里有些事情我不理解。我感觉这对于新Python程序员来说可能是一个常见的“陷阱”,但是我能想到的用来描述问题的所有术语都是如此通用,以至于我的搜索仅返回了大量无关的答案。您能否向我解释这里发生了什么,而不是我的预期,最好还应说明为实现几种/ different /方法的理想效果而应该做的事情。
1 回答
慕盖茨4494581
TA贡献1850条经验 获得超11个赞
问题是这条线...
attrdict["test%s"%i]= types.MethodType(lambda self: i)
当您定义一个lambda
引用了不是其参数之一的变量的变量时,该变量将在lambda
实际调用该变量时从定义该变量的作用域中进行解析,因此您将始终获得的当前值i
是,而不是i
定义时的值lambda
。
在您的情况下,的值i
将2
在for i in range(3)
循环完成后结束,因此在创建时需要创建一个闭包以绑定i
到特定值lambda
,方法是将行更改为...
attrdict["test%s"%i]= types.MethodType(lambda self, i=i: i)
添加回答
举报
0/150
提交
取消