2015-05-18 5 views
15

После многого поиска я обнаружил, что есть несколько способов добавить связанный метод или методы несвязанного класса к существующим объектам экземпляра.Любой элегантный способ добавить метод к существующему объекту в python?

Такие способы включают подходы к принятому ниже коду.

import types 


class A(object): 
    pass 


def instance_func(self): 
    print 'hi' 

def class_func(self): 
    print 'hi' 

a = A() 

# add bound methods to an instance using type.MethodType 
a.instance_func = types.MethodType(instance_func, a)    # using attribute 
a.__dict__['instance_func'] = types.MethodType(instance_func, a) # using __dict__ 

# add bound methods to an class 
A.instance_func = instance_func 
A.__dict__['instance_func'] = instance_func 

# add class methods to an class 
A.class_func = classmethod(class_func) 
A.__dict__['class_func'] = classmethod(class_func) 

Что меня раздражает, набрав имя функции, instance_func или class_func дважды.

Есть ли простой способ добавить существующую функцию в класс или экземпляр, не набрав имя функции еще раз?

Например, A.add_function_as_bound_method(f) будет намного более элегантным способом добавить существующую функцию к экземпляру или классу, так как функция уже имеет атрибут __name__.

ответ

43

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

Тем не менее, вы можете использовать functools.partial предварительно связать функцию и сохранить его в словаре объектов, поэтому он может быть доступен как метод:

>>> from functools import partial 
>>> class Dog: 
     def __init__(self, name): 
      self.name = name 


>>> d = Dog('Fido') 
>>> e = Dog('Buddy') 
>>> def bark(self):     # normal function 
     print('Woof! %s is barking' % self.name) 

>>> e.bark = partial(bark, e)  # pre-bound and stored in the instance 
>>> e.bark()      # access like a normal method 
Woof! Buddy is barking 

Это несколько элегантный способ добавить метод к существующему объекту (без необходимости изменения его класса и без влияния на другие существующие объекты).

Последующая деятельность по итогам Комментарий:

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

>>> def add_method(obj, func): 
     'Bind a function and store it in an object' 
     setattr(obj, func.__name__, partial(func, obj)) 

Используйте это так:

>>> add_method(e, bark) 
>>> e.bark() 
Woof! Fido is barking 

Надеюсь, что это именно то, что вам нужно :-)

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