猿问

如何通过循环创建新的Python方法?

我正在研究从数据动态生成Python类。(目的是让用户在不知道任何Python的情况下,在一个简单的文件中指定一些软件测试)。我遇到了意想不到的效果;作为一个玩具示例,可以快速检查是否可以根据命名方案创建方法,我做了以下工作:


import unittest


attrdict = {}

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 /方法的理想效果而应该做的事情。


HUX布斯
浏览 146回答 1
1回答

慕盖茨4494581

问题是这条线...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)
随时随地看视频慕课网APP

相关分类

Python
我要回答