Динамическое назначение реализации функции в 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)