MetaPython: добавление методов в класс - PullRequest
1 голос
/ 19 июля 2009

Я хотел бы добавить некоторые методы к определению класса во время выполнения. Однако при выполнении следующего кода я получаю некоторые неожиданные (для меня) результаты.

test.py

class klass(object):
    pass

for i in [1,2]:
    def f(self):
        print(i)
    setattr(klass, 'f' + str(i), f)

При тестировании в командной строке я получаю следующее:

>>> import test
>>> k = test.klass()
>>> k.f1()
2
>>> k.f2()
2

Почему k.f1() возвращает 2 вместо 1? Мне это кажется довольно интуитивным.

примечания

Этот тест был выполнен с использованием python3.0 на компьютере kubuntu.

Ответы [ 2 ]

11 голосов
/ 19 июля 2009

Это обычная проблема привязки - вы хотите раннее связывание для использования i внутри функции, а Python выполняет позднее связывание для нее. Вы можете принудительно установить более раннюю привязку следующим образом:

class klass(object):
    pass

for i in [1,2]:
    def f(self, i=i):
        print(i)
    setattr(klass, 'f' + str(i), f)

или путем переноса f во внешний слой функции, принимая i в качестве аргумента:

class klass(object):
    pass

def fmaker(i):
    def f(self):
        print(i)
    return f

for i in [1,2]:
    setattr(klass, 'f' + str(i), fmaker(i))
0 голосов
/ 19 июля 2009

Мне кажется, это потому, что print (i) печатает i не по значению , а по ссылке . Таким образом, при выходе из цикла for i имеет значение 2 , которое будет напечатано оба раза.

...