0

为了自动生成参数化测试,我试图通过冻结现有方法的一些参数来将方法添加到类中。这是一段 Python 3 代码

class A:
    def f(self, n):
        print(n)

params = range(10)

for i in params:
    name = 'f{0}'.format(i)
    method = lambda self: A.f(self, i)
    setattr(A, name, method)

但是,以下几行会产生相当令人失望的输出

a = A()
a.f0()

打印“9”(而不是“0”)。我一定做错了什么,但我看不出是什么。你能帮我吗 ?

非常感谢


编辑:这个问题确实是重复的。我想承认所有评论的质量,它们比原始答案更深入。

4

2 回答 2

1

尝试

method = lambda self, i=i: A.f(self, i)

因为否则当你调用方法i的值可能已经改变了

于 2014-02-07T16:34:33.193 回答
1

在 Python 中“冻结”参数的最佳方法是使用functools.partial. 它大致相当于 warwaruk 的 lambda 版本,但是如果您有一个带有很多参数的函数但只想冻结其中的一两个(或者如果您只知道某些参数而不关心其余参数),那么使用partial会更优雅您只需指定要冻结的参数,而不必在 lambda 中重复整个函数签名。

您的程序的示例:

class A:
    def f(self, n):
        print(n)

from functools import partial

for i in range(10): # params
    setattr(A, 'f{0}'.format(i), partial(A.f, n=i))

根据您使用的 Python 3 版本,您可能不需要0在字符串格式占位符中包含 ;从 3.1,iirc 开始,它应该被自动替换。

于 2014-02-07T16:40:46.247 回答