tags:

views:

383

answers:

3

I would like to create a class that effectively does this (mixing a little PHP with Python)

  class Middle(object) :
    #  self.apply is a function that applies a function to a list
    #  e.g   self.apply = []  ... self.apply.append(foobar)       
    def __call(self, name, *args) :
       self.apply(name, *args)   

Thus allowing for code to say:

   m = Middle()
   m.process_foo(a, b, c)

In this case __call() is the PHP __call() method which is invoked when a method is not found on an object.

+1  A: 

Consider passing arguments to your methods as arguments, not encoded into the method name which will then be magically used as an argument.

Where are you writing code that doesn't know what methods it will be calling?

Why call c.do_Something(x) and then unpack the method name instead of just calling c.do('Something', x) ?

In any case it's easy enough to handle unfound attributes:

class Dispatcher(object):
    def __getattr__(self, key):
       try:
           return object.__getattr__(self, key)
       except AttributeError:
           return self.dispatch(key)

    def default(self, *args, **kw):
        print "Assuming default method"
        print args, kw

    def dispatch(self, key):
        print 'Looking for method: %s'%(key,)
        return self.default

A test:

>>> d = Dispatcher()
>>> d.hello()
Looking for method: hello
Assuming default method
() {}

This seems to be fraught with "gotchas" - the thing returned by getattr is going to be presumed to be not just a function, but a bound method on that instance. So be sure to return that.

Joe Koberg
+3  A: 

You need to define __getattr__, it is called if an attribute is not otherwise found on your object.

Notice that getattr is called for any failed lookup, and that you don't get it like a function all, so you have to return the method that will be called.

def __getattr__(self, attr):
  def default_method(*args):
    self.apply(attr, *args)
  return default_method
kaizer.se
A: 

I actually did this recently. Here's an example of how I solved it:

class Example:
    def FUNC_1(self, arg):
        return arg - 1

    def FUNC_2(self, arg):
        return arg - 2

    def decode(self, func, arg):
        try:
            exec( "result = self.FUNC_%s(arg)" % (func) )
        except AttributeError:
            # Call your default method here
            result = self.default(arg)

        return result

    def default(self, arg):
        return arg

and the output:

>>> dude = Example()
>>> print dude.decode(1, 0)
-1
>>> print dude.decode(2, 10)
8
>>> print dude.decode(3, 5)
5
KingRadical
that's absolutely horrible. You could use getattr instead: `result = getattr(self, "FUNC_%d" % func, self.default)(arg)`
kaizer.se