Python Introspection:在运行时定义动态类方法

时间:2012-12-26 09:47:23

标签: python reflection introspection

我正在尝试创建一个单元测试,它会检查mymodule中的每个函数是否都有自己的TestCase实例。
为了减少样板代码和手动操作,我想使用内省/反射将lambda函数作为类方法动态添加到最初为空的类Test_TestCases
以下代码类型的工作 - 它确实将lambdas添加为类方法,unittest.main()找到并正确调用它们。

import unittest
from unittest import TestCase

import mymodule

class Test_TestCases(TestCase):
"""Class whose test_* methods will be created during runtime."""
    pass

################################################################################

if __name__ == "__main__":
    for item in dir(mymodule):
        attr = getattr(pws, item)
        if callable(attr):
            testname = "Test_%s" % item
            setattr(Test_TestCases, "test_%s_is_tested" % item,
                    lambda self: self.assertTrue(testname in globals()) and
                    issubclass(getattr(globals(), testname), TestCase))
    unittest.main()

问题是,即使我的单元测试模块中有未经测试的功能,所有测试都会成功 经过一番尝试后,我发现每次调用testname时变量lambda都具有相同的值。
我可以将这段代码的问题最小化,以实现可重现性:

lambdas = []
for i in range(5):
    lambdas.append(lambda: str(i))
print ", ".join(f() for f in lambdas)

我期待这个输出:

0, 1, 2, 3, 4

但我得到了:

4, 4, 4, 4, 4

似乎懒惰地初始化了lambda 任何人都可以解释一下这种行为,或者给我一个关于如何正确实现目标的提示吗?

提前致谢

1 个答案:

答案 0 :(得分:1)

使用另一个包装函数的阴影testname

def assertion(testname=testname):
    def function(self):
        return self.assertTrue(testname in globals()) and issubclass(getattr(globals(), testname), TestCase))

    return function

setattr(Test_TestCases, "test_%s_is_tested" % item, assertion())