Объекты исправлений обезьяны Python не работают должным образом

Я пытаюсь изучить исправление обезьяны Python. У меня есть простой пример, когда я пытаюсь исправить только один экземпляр, а не сам класс.

Мой код:

# add.py
import types


class Math(object):
    def __init__(self):
        self.name = ''

    def add(self, x, y, name):
        self.name = name
        print 'calling from ', self.name
        return x + y

    def monkey_patch(self):
        add = self.add

        def squared_sum(x, y):
            return x**2 + y**2
        add = types.MethodType(squared_sum, self)


if __name__ == '__main__':
    math = Math()
    print math.add(3, 4, 'before monkey_patching')
    math.monkey_patch()
    print math.add(3, 4, 'after monkey_patching')

Ожидаемый результат:

calling from  before monkey_patching
7
calling from  after monkey_patching
25

Созданные выходные данные:

calling from  before monkey_patching
7
calling from  after monkey_patching
7

Может кто-нибудь указать, где я ошибаюсь. А также как я могу исправить метод добавления обезьяны, когда я делаю это из другого файла, то есть когда я импортирую класс Math из add.py в другой файл, как я могу исправить его метод добавления.


person Shankar    schedule 10.01.2014    source источник


Ответы (1)


Ваш код не делает то, что вы думаете:

def monkey_patch(self):
    add = self.add # add now points to self.add
    def squared_sum(x, y):
        return x**2 + y**2
    add = types.MethodType(squared_sum, self) # add now points to squared_sum
# method ends, add and squared_sum are abandoned

На самом деле это не меняется self.add. Кроме того, squared_sum не принимает аргументы self или name, в отличие от add, и не имеет print, который есть у add. Чтобы это работало полностью, выполните:

def monkey_patch(self):
    def squared_sum(self, x, y, name):
        self.name = name
        print 'calling from ', self.name
        return x**2 + y**2
    self.add = types.MethodType(squared_sum, self) 

Чтобы исправить вне определения класса:

math = Math()

def func(self, x, y, name):
    return x ** y

math.add = types.MethodType(func, math)
person jonrsharpe    schedule 10.01.2014
comment
Работает идеально! Были сомнения. self.add = types.MethodType(squared_sum, self) показывает атрибут экземпляра, определенный вне предупреждения init. Теперь, как я могу переместить self.add в конструктор? - person Shankar; 10.01.2014
comment
Вы используете PyCharm или что-то в этом роде? Конечно, вы определяете вне __init__, в этом весь смысл того, что вы делаете; вы можете игнорировать предупреждение. - person jonrsharpe; 10.01.2014
comment
точно! Я использую PyCharm!! Большое спасибо! - person Shankar; 10.01.2014