In python, a "function object", that is to say an object which can be called as a function, is simply an instance of a class which has a __call__ method. An example is

class FuncObj(object):
  def __call__(self, *args):
    print("args were %s." % str(args))
func = FuncObj()
func(1,2,3) # output -> args were (1, 2, 3)

Since this object is callable, we may want to install it as a method in another class. Suppose I create a class and and instance like this

class Thing(object):
  pass
thing = Thing()

how can I add a method foo in the class Thing so that the call thing.foo(3) is equivalent to func(thing, 3) ?
The naive way to do this doesn't work:

Thing.foo = func
thing.foo(3) # -> output: args were (3,)

the instance 'thing' is not passed to func.__call__ , as one would expect from an instance method. Second try

Thing.foo = func.__call__
thing.foo(3) # same failure: args were (3,)

I ended up wrapping func into a true function like this

def asFunction(obj, name=""):
  def wrapper(*args, **kwd):
    return obj(*args, **kwd)
  if name:
    wrapper.__name__ = name
  wrapper.wrapped = obj
  return wrapper

# third try
Thing.foo = asFunction(func, "foo")
thing.foo(3) # output: args were (<main.Thing object...>, 3)  Success !
thing.foo.wrapped # <- access to the wrapped object func through Thing.foo.

Any comments ?
If someone knows a better way to do this, please add to this thread :)

Recommended Answers

All 3 Replies

You might get further if class Thing inherits class FuncObj.

You might get further if class Thing inherits class FuncObj.

Yes it's true, however this event is unlikely. Here the idea is rather to add methods to an existing class. In fact I had this problem when subclassing the class cmd.Cmd from the standard lib, which helps you build command interpreters. With this class, if you want to add a command to your interpreter, say "gcc", then you must add a method do_gcc to your interpreter. But as you can imagine, the action of such a command can be very complicated if you want to support a rich syntax with many different options. If you have many such commands, it looks like a bad idea to write a method for each command in your interpreter class. It's better to write a small interpreter class and to dynamically add methods written in separate modules. For a complex command, it looks natural to define a callable class instead of a function. This class holds the methods that you need to implement the algorithm of the command's action. With this design, once the code for the interpreter is written, you can freely choose and modify the set of commands that you want to run.

I found a much more canonical solution in this tutorial about descriptors http://users.rcn.com/python/download/Descriptor.htm. One only need to add a __get__ method to turn the function object into a descriptor. Now accessing thing.foo will return a bounded method. Here is the code

import types

class FuncObj(object):
  def __call__(self, *args):
    print("args were %s." % str(args))

  def __get__(self, obj, objtype=None):
    # having a __get__ turns a FunctObj into a descriptor
    return types.MethodType(self, obj, objtype)
func = FuncObj()

class Thing(object):
  pass
thing = Thing()

Thing.foo = func
thing.foo(3)
"""
my output --->
args were (<__main__.Thing object at 0xb7bce28c>, 3).
"""
commented: Great! +6
Be a part of the DaniWeb community

We're a friendly, industry-focused community of developers, IT pros, digital marketers, and technology enthusiasts meeting, networking, learning, and sharing knowledge.