为了自动生成参数化测试,我试图通过冻结现有方法的一些参数来向类中添加方法。这是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”)。我一定做错了什么,但我看不出来。你能帮忙吗?
非常感谢
编辑:这个问题确实是重复的。我要感谢所有评论的质量,这些评论比原始答案更深刻。
答案 0 :(得分:1)
尝试
method = lambda self, i=i: A.f(self, i)
因为否则当您调用方法i
时,其值可能已更改
答案 1 :(得分:1)
在Python中“冻结”参数的最佳方法是使用functools.partial
。它大致相当于warwaruk的lambda版本,但是如果你有一个带有大量参数的函数但只想冻结其中的一个或两个(或者如果你只知道某些参数而不关心其余的那些)使用{{1}因为你只指定要冻结的参数而不必重复lambda中的整个函数签名,所以更优雅。
您的计划的一个示例:
partial
根据您使用的Python 3版本,您可能不需要在字符串格式占位符中包含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))
;从3.1开始,iirc,它应该自动替换。