This answer解释了如何动态创建测试用例。
答案的代码:
class Tests(unittest.TestCase):
def check(self, i, j):
self.assertNotEquals(0, i-j)
for i in xrange(1, 4):
for j in xrange(2, 6):
def ch(i, j):
return lambda self: self.check(i, j)
setattr(Tests, "test_%r_%r" % (i, j), ch(i, j))
我已经测试过并且有效,但我不能弄明白如何?
我无法理解这里的lambda self:
魔法,主要是:
functools.partial()
完全相反(即创建一个包含 extra 参数的包装函数尚未知道)self
是一个有意义的关键字,还是lambda spam
也能正常运作?.check()
在class
范围之外完全正常?lambda
(更不用说我同意Guido和Alex认为 是一个眼睛,我希望没有:)< / LI>
醇>
答案 0 :(得分:5)
首先:从函数返回lambda,以防止稍后使用i
和j
的修改值。
与以下内容比较:
for i in xrange(1, 4):
for j in xrange(2, 6):
setattr(Tests, "test_%r_%r" % (i, j), lambda self: self.check(i, j))
这将无法按预期工作,因为所有lambda将共享相同的命名空间,并将在循环结束后使用i
和j
的值。如果我们使用单独的函数调用,每次在调用函数的时间点捕获i
和j
的值时,我们会引入一个新的闭包。
我们可以通过将i
和j
的当前值保存为lambda的默认参数来实现相同的目标。为了更好地衡量,我们还使用itertools.product
来避免嵌套循环:
from itertools import product
from operator import methodcaller
for i, j in product(range(1, 4), range(2, 6)):
setattr(Tests, "test_%r_%r" % (i, j),
lambda self, i=i, j=j: self.check(i, j))
这里使用的lambda是否与functools.partial()完全相反(即创建一个包含一个尚未知的额外参数的包装函数)
不是真的。它只是调用check(i, j)
方法作为参数。这用于动态地将方法添加到Tests
类。
自我是一个有意义的关键字还是lambda垃圾邮件也能正常工作?
spam
也可以。由于约定,他们在这里选择self
因为lambda代表一种方法。
lambda评估的重点是什么?
在test_[i]_[j]()
的实例上调用Tests
。
为什么.check()在类范围之外完全没问题?
因为它在lambda中只会稍后使用Tests
的实例作为self
参数调用。
答案 1 :(得分:3)
lambda返回一个函数。 self
是它的参数,i和j在其中封闭
因此,ch(i,j)是i和j的函数,返回 self 的函数。
self在Python中没有任何神奇的含义 - 除了一些内置函数之外,每个变量和函数都是显式的。但是只要这些方法附在课堂上,自我就成了他们的第一个论点。
这意味着
Tests类获取多个名为check_i_j的方法
每个人都有值i和j 封闭
他们每个都有第一个名为self
的参数,这是好的,因为它们是在类中定义的,它们是实例方法,因此它们的第一个参数应该按惯例调用自我
答案 2 :(得分:3)
a_function = lambda x: do_something_with(x)
相当于
def a_function(x):
return do_something_with(x)
在您的特定示例中,创建的函数是实例方法。因此,例如你可以写:
class Tests:
...
test_1_2 = lambda self: self.check(1, 2)
这相当于:
class Tests:
...
def test_1_2(self):
return self.check(1, 2)
现在,由于标识符是动态生成的,因此使用setattr
。
- 这里使用的lambda是否与
醇>functools.partial()
完全相反(即创建一个额外的包装函数) 参数尚未知晓)
不,不是真的。事实上,partial
也可以在这里使用。
test_1_2 = lambda self: self.check(1, 2)
会变成
test_1_2 = partial(Tests.check, i=1, j=2)
- 自我是一个有意义的关键字还是lambda垃圾邮件也能正常工作?
醇>
实例方法的第一个参数始终需要是实例。 约定是命名该参数self
,但您可以使用任何其他名称。我不建议它,因为它会使你的代码更难阅读和理解。
- lambda评估的重点是什么?
醇>
lambda
创建匿名函数,在调用时评估任何函数。
- 为什么.check()在类范围之外完全没问题?
醇>
不是。它是self.check()
,其中self
是Tests
类的实例。