Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Any elegant way to add a method to an existing object in python?

Tags:

After a lot of searching, I have found that there are a few ways to add an bound method or unbound class methods to an existing instance objects

Such ways include approaches the code below is taking.

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)

What makes me annoying is, typing the function's name, instance_func or class_func twice.

Is there any simple way to add an existing function to an class or instance without typing the function's name again?

For example, A.add_function_as_bound_method(f) will be far much elegant way to add an existing function to an instance or class since the function already has __name__ attribute.

like image 883
June Avatar asked May 18 '15 03:05

June


People also ask

Is it possible to add a method to an object after creation?

We cannot add a method as it is the case with a normal object. To make a method in an object constructor it has to be added inside the object constructor.

How do I add a method to an existing class in Python?

Use the types. MethodType function to add a method to an existing object instance, e.g. my_inst. increase_salary = types.

What is the __ add __ method in Python?

Python __add__() method adds two objects and returns a new object as a resultant object in Python. The below example returns a new object, Python3.


1 Answers

Normally, functions stored in object dictionaries don't automatically turn into boundmethods when you look them up with dotted access.

That said, you can use functools.partial to pre-bind the function and store it in the object dictionary so it can be accessed like a method:

>>> 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

This is a somewhat elegant way to add a method to an existing object (without needing to change its class and without affecting other existing objects).

Follow-up to Comment:

You can use a helper function to add the pre-bound function is a single step:

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

Use it like this:

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

Hope this is exactly what you need :-)

like image 90
Raymond Hettinger Avatar answered Sep 18 '22 14:09

Raymond Hettinger