Использование setattr для замораживания некоторых параметров метода
Чтобы автоматически генерировать параметризованные тесты, я пытаюсь добавить методы в класс, заморозив некоторые параметры существующего метода. Вот кусок кода 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"). Должно быть, я что-то делаю не так, но не вижу, что. Вы можете помочь?
большое спасибо
Изменить: этот вопрос действительно дубликат. Я хотел бы отметить качество всех комментариев, которые намного глубже, чем грубый ответ.
2 ответа
Пытаться
method = lambda self, i=i: A.f(self, i)
потому что иначе, когда вы вызываете метод i
возможно, значение изменилось
Лучший способ "заморозить" параметры в Python - это использовать functools.partial
, Это примерно эквивалентно лямбда-версии warwaruk, но если у вас есть функция с большим количеством аргументов, вы хотите заморозить только один или два из них (или если вы знаете только определенные аргументы и не заботитесь об остальных), используя partial
более элегантно, поскольку вы указываете только те аргументы, которые хотите заморозить, вместо того, чтобы повторять всю сигнатуру функции в лямбда-выражении.
Пример для вашей программы:
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, он должен быть автоматически заменен.