Как вы привязываете методы к объектам в Python во время выполнения?
Я хочу добавить метод к объекту во время выполнения, как при этом.
class C(object):
def __init__(self, value)
self.value = value
obj = C('test')
def f(self):
print self.value
setattr(obj, 'f', f)
obj.f()
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: f() takes exactly 1 argument (0 given)
Но похоже, что setattr не привязывает метод к объекту. Можно ли сделать это?
3 ответа
Ты можешь использовать MethodType
из модуля типов:
import types
obj.f = types.MethodType(f, obj)
obj.f()
Но тебе это действительно нужно? Ищите декораторов (например), это более элегантный способ добавить необходимую функциональность в класс.
Есть способ, который я обнаружил, используя пространство привязки locals() и команду exec(). Сначала вы должны создать функциональный объект из встроенной функции exec() и извлечь его:
def make_function(name, parameter, commands):
func = 'def {name}({parameter}):'.format(name=name, parameter=parameter)
for line in commands:
func += '\n\t' + line
exec(func)
return locals()[name]
>>> func = make_function('help', 'pay', ['pay+=2', 'pay*=5', 'credit = pay//3', 'return credit'])
>>> func(8)
16
Затем вам нужна другая функция, которая создает объект экземпляра с использованием атрибута dict. Диктовка объекта подобна внутреннему словарю атрибутов, к которому можно получить доступ через. команды, он делает объект Python похожим на объект JavaScript.
def create_object(names, values):
assert len(names) == len(values)
exec('class one: pass')
obj = locals()['one']()
for i in range(len(names)):
obj.__dict__[names[i]] = values[i]
return obj
>>> func = make_function('help', 'pay', ['pay+=2', 'pay*=5', 'credit = pay//3', 'return credit'])
>>> test_obj = create_object(['help', 'interest', 'message'], [func, 0.5, 'please pay by thursday.'])
>>> test_obj.help(7)
15
>>> test_obj.interest
0.5
>>> test_obj.message
'please pay by thursday.'
Эта функция, по сути, объединяет списки, чтобы создать набор атрибутов для вашего экземпляра объекта.
По факту, seattr
не будет передавать себя / объект подключаемому методу.
Так что вы могли бы сделать что-то вроде этого:
class C(object):
def __init__(self, value):
self.value = value
obj = C('some thing')
def make_method(_object, *args, **kwargs):
def f(self=_object):
print self.value
return f
setattr(obj, 'f', make_method(obj))
obj.f()
Это работает потому что f()
имеет доступ к make_method()
область действия, так как это внутренняя / вложенная / замыкающая функция.