Question

I want to assign a function implementation dynamically.

Let's start with the following:

class Doer(object):

    def __init__(self):
        self.name = "Bob"

    def doSomething(self):
        print "%s got it done" % self.name

def doItBetter(self):
    print "Done better"

In other languages we would make doItBetter an anonymous function and assign it to the object. But no support for anonymous functions in Python. Instead, we'll try making a callable class instance, and assign that to the class:

class Doer(object):

    def __init__(self):
        self.name = "Bob"

class DoItBetter(object):

    def __call__(self):
        print "%s got it done better" % self.name

Doer.doSomething = DoItBetter()
doer = Doer()
doer.doSomething()

That gives me this:

Traceback (most recent call last): Line 13, in doer.doSomething() Line 9, in call print "%s got it done better" % self.name AttributeError: 'DoItBetter' object has no attribute 'name'

Finally, I tried assigning the callable to the object instance as an attribute and calling it:

class Doer(object):

    def __init__(self):
        self.name = "Bob"

class DoItBetter(object):

    def __call__(self):
        print "%s got it done better" % self.name


doer = Doer()
doer.doSomething = DoItBetter()
doer.doSomething()

This DOES work as long as I don't reference self in DoItBetter, but when I do it gives me an name error on self.name because it's referencing the callable's self, not the owning class self.

So I'm looking for a pythonic way to assign an anonymous function to a class function or instance method, where the method call can reference the object's self.

Was it helpful?

Solution

Your first approach was OK, you just have to assign the function to the class:

class Doer(object):
    def __init__(self):
        self.name = "Bob"

    def doSomething(self):
        print "%s got it done" % self.name

def doItBetter(self):
    print "%s got it done better" % self.name

Doer.doSomething = doItBetter

Anonymous functions have nothing to do with this (by the way, Python supports simple anonymous functions consisting of single expressions, see lambda).

OTHER TIPS

yak's answer works great if you want to change something for every instance of a class.

If you want to change the method only for a particular instance of the object, and not for the entire class, you'd need to use the MethodType type constructor to create a bound method:

from types import MethodType

doer.doSomething = MethodType(doItBetter, doer)
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top