2015-11-27 7 views
2

Я хочу добавить метод к объекту во время выполнения, как таким образом.Как вы связываете методы с объектами в 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 не связывает этот метод с объектом. Можно ли сделать это?

+0

Кроме того, я написал сообщение в блоге об этой теме в python: https://creatism.wordpress.com/2015/10/26/creating-function-and-class-objects-in-python/ –

ответ

2

Вы можете использовать MethodType из types модуля:

import types 

obj.f = types.MethodType(f, obj)  
obj.f() 

Но вы действительно нуждаетесь в этом? Ищите декораторов (например), это более элегантный способ добавить необходимую функциональность в класс.

+0

Я разрабатываю фабричную функцию, которая генерирует объекты на основе того, какой параметр предоставляется. Итак, если я хочу определить лошадь, я просто называю AnimalFactory (properties = [HasFourLegs, CanRun]). Я забыл, что называется этой парадигмой. – Irvan

1

Существует способ, который я обнаружил, используя пространство привязки 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 атрибут . 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.' 

Эта функция существенно упрощает разделение списков вместе, чтобы создать набор атрибутов для объекта экземпляра.

+0

с использованием местных жителей () выглядит как overkill, хотя ... Я предполагаю, что действительно нет простого способа, такого как setattr (obj, 'f', classmethod (f)) (не работает для экземпляра объекта, работает для классов). – Irvan

+0

Вы можете попробовать использовать obj .__ dict __ ['f'] = classmethod (f) –

1

Фактически, 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() сферы, так как это внутренняя/вложенная функция/закрытия.

+0

Я думаю, что может не работать для более сложных функций, которые имеют параметры, особенно * args. – Irvan

+0

Почему? Да конечно. – felipsmartins

+0

http://pastebin.com/fpQ9nihn – Irvan

 Смежные вопросы

  • Нет связанных вопросов^_^