piRSquared
piRSquared

Reputation: 294248

add method with a specific name to already created class instance

Setup

Suppose you have a class instance that has already been instantiated and you need to attach a function as a method to the class.

class ClassA(object):
    def __init__(self):
        self.attr1 = 'hello'
        self.attr2 = 'world'

    def get_attr1(self):
        return self.attr1

For whatever reason, we've neglected to create the get_attr2 method.

If we create an instance of ClassA:

a = ClassA()

We could define a function and even call the first parameter self.

def get_attr2(self):
    return self.attr2

However, this can only be called like

get_attr2(a)

Question

How do we set up being able to call the function like a method?

a.get_attr2()

Upvotes: 3

Views: 487

Answers (2)

Paul Cornelius
Paul Cornelius

Reputation: 10926

In Python 3 you can just define a function (taking a self variable) and bind it to a name in the class, like this:

#! python3

class A:
    def b(self):
        print("I am b")

def c(self):
    print("I am c")

A.c = c   # Now A has a method named 'c'

an_a = A()
an_a.b()
an_a.c()

This program prints "I am b" followed by "I am c" as you would expect. This will perhaps not result in the most easily understood program you've ever seen, but it works.

Upvotes: 1

piRSquared
piRSquared

Reputation: 294248

Solution

methods are a specific type of function. That type defines how methods behave and specify that they can be called via the dot convention.

To solve this we need to import types. Then I'll create a simple function to attach any other function as a method to an existing instance.

import types

def attach_method(class_instance, name, function):
    if name not in class_instance.__dict__.keys():
        class_instance.__dict__[name] = types.MethodType(function, class_instance)

With this i run:

attach_method(a, 'get_attr2', get_attr2)

And that's it.

Note:

function's have no name, so I have to pass a name.

Motivation

I have classes in which I want methods defined for each of a long list of other classes. I define these other classes in a separate module. These classes are created at a rapid pace. I thought it would be easier to maintain if I read this other module and generated a separate method that gives access to each class inside the module. This may or may not have been the best solution, but it is what motivated me to find a way to do this. I still haven't seen a more succinct way to do this.

Upvotes: 1

Related Questions