質問

in order to automatically generate parameterized tests, I am trying to add methods to a class in by freezing some parameters of an existing method. Here is the piece of Python 3 code

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)

However, the following lines then produce rather disappointing output

a = A()
a.f0()

prints "9" (instead of "0"). I must be doing something wrong, but I can't see what. Can you help ?

Thanks a lot


Edit: this question is indeed a duplicate. I would like to acknowledge the quality of all comments, which go much deeper than the raw answer.

役に立ちましたか?

解決

Try

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

because otherwise when you call the method i's value may have changed

他のヒント

The best way to "freeze" parameters in Python is to use functools.partial. It's roughly equivalent to warwaruk's lambda version, but if you have a function with lots of arguments yet only want to freeze one or two of them (or if you only know certain arguments and don't care about the rest) using partial is more elegant as you only specify the arguments you want to freeze rather than having to repeat the whole function signature in the lambda.

An example for your program:

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))

Depending on which version of Python 3 you're using, you may not need to include the 0 in the string format placeholder; starting with 3.1, iirc, it should be automatically substituted.

ライセンス: CC-BY-SA帰属
所属していません StackOverflow
scroll top