Динамическое назначение реализации функции в Python

Я хочу динамически назначать реализацию функции.

Начнем со следующего:

class Doer(object):

    def __init__(self):
        self.name = "Bob"

    def doSomething(self):
        print "%s got it done" % self.name

def doItBetter(self):
    print "Done better"

В других языках мы сделаем doItBetter анонимной функцией и назначим ее объекту. Но поддержка анонимных функций в Python не поддерживается. Вместо этого мы попытаемся создать экземпляр класса вызываемого класса и назначим его классу:

class Doer(object):

    def __init__(self):
        self.name = "Bob"

class DoItBetter(object):

    def __call__(self):
        print "%s got it done better" % self.name

Doer.doSomething = DoItBetter()
doer = Doer()
doer.doSomething()

Это дает мне следующее:

Traceback (последний последний вызов): строка 13, в     doer.doSomething() Линия 9, в вызов    print "% s сделал это лучше" % self.name AttributeError: объект DoItBetter не имеет атрибута 'name'

Наконец, я попытался назначить вызываемый экземпляр объекта как атрибут и называть его:

class Doer(object):

    def __init__(self):
        self.name = "Bob"

class DoItBetter(object):

    def __call__(self):
        print "%s got it done better" % self.name


doer = Doer()
doer.doSomething = DoItBetter()
doer.doSomething()

Это работает до тех пор, пока я не ссылаюсь на self в DoItBetter, но когда я это делаю, он дает мне ошибку имени в self.name, потому что ссылается на вызываемый self, а не на собственный класс self.

Итак, я ищу питоновский способ присвоить анонимную функцию функции класса или экземпляру, где вызов метода может ссылаться на объект self.

Ответ 1

Ваш первый подход был в порядке, вам просто нужно назначить функцию классу:

class Doer(object):
    def __init__(self):
        self.name = "Bob"

    def doSomething(self):
        print "%s got it done" % self.name

def doItBetter(self):
    print "%s got it done better" % self.name

Doer.doSomething = doItBetter

Анонимные функции не имеют к этому никакого отношения (кстати, Python поддерживает простые анонимные функции, состоящие из отдельных выражений, см. lambda).

Ответ 2

Ответ на yak отлично работает, если вы хотите что-то изменить для каждого экземпляра класса.

Если вы хотите изменить метод только для определенного экземпляра объекта, а не для всего класса, вам нужно будет использовать конструктор типа MethodType для создания связанного метода:

from types import MethodType

doer.doSomething = MethodType(doItBetter, doer, Doer)