orig_foo
- это глобальная переменная, которая меняет значение при каждом прохождении цикла. После завершения цикла orig_foo
относится к B.foo
.
Внутренние функции foo
(один или каждый проход по циклу) обе используют глобальное значение для orig_foo
при их вызове. Таким образом, они оба называют B.foo(self)
.
При вызове «несвязанного метода», такого как orig_foo
, Python2 проверяет, является ли первый аргумент экземпляром соответствующего класса. A().foo()
не проходит эту проверку. (Интересно, что эта проверка была удалена в Python3, поэтому не возникнет TypeError, и эту ошибку может стать труднее найти).
Чтобы это исправить, вы должны привязать значение orig_foo
к соответствующему klass
.
Вы можете сделать это, сделав orig_foo
локальной переменной foo
. Один из способов сделать это - сделать orig_foo
аргументом foo
со значением по умолчанию. Python связывает значения по умолчанию во время определения функции. Так orig_foo=orig_foo
связывает локальную переменную orig_foo
с текущим значением klass.foo
:
for klass in A, B:
orig_foo = klass.foo
def foo(self, orig_foo=orig_foo):
return orig_foo(self) * 2
klass.foo = foo