10

Is it possible to implement generic method handlers in python which allow for calling of non-existent functions? Something like this:

class FooBar:
  def __generic__method__handler__(.., methodName, ..):
    print methodName

fb = FooBar()
fb.helloThere()

-- output --
helloThere
Chris Morgan
  • 73,264
  • 19
  • 188
  • 199
paweloque
  • 17,185
  • 25
  • 75
  • 131
  • This still leaves the question of why you would want to do this. – Chris Morgan Jun 24 '11 at 12:45
  • @ChrisMorgan It might allow method names to automatically generated using regular expressions, so any method name that matched the regular expression could be used as an alias for one particular method. – Anderson Green Aug 07 '13 at 22:25
  • @AndersonGreen: but why would you want to do that? – Chris Morgan Aug 08 '13 at 15:32
  • 1
    @ChrisMorgan How about general decorator, holding an object and doing some decoration (logging, lazy initialization?) over all its methods? – Tregoreg Jul 22 '14 at 01:36

3 Answers3

15

The first thing to remember is that methods are attributes which happen to be callable.

>>> s = " hello "
>>> s.strip()
'hello'
>>> s.strip
<built-in method strip of str object at 0x000000000223B9E0>

So you can handle non-existent methods in the same way you would handle non-existent attributes.

This is usally done by defining a __getattr__ method.

Now you're going hit the additional complexity which is the difference between functions and method. Methods need to be bound to an object. You can take a look at this question for a discussion of this.

So I think you'll want something like this:

import types

class SomeClass(object):
    def __init__(self,label):
        self.label = label

    def __str__(self):
        return self.label

    def __getattr__(self, name):
        # If name begins with f create a method
        if name.startswith('f'):
            def myfunc(self):
                return "method " + name + " on SomeClass instance " + str(self)
            meth = types.MethodType(myfunc, self, SomeClass)
            return meth
        else:
            raise AttributeError()

Which gives:

>>> s = SomeClass("mytest")
>>> s.f2()
'method f2 on SomeClass instance mytest'
>>> s.f2
<bound method SomeClass.myfunc of <__main__.SomeClass object at 0x000000000233EC18>>

However, I'd probably recommend against using this. If you tell us the problem you're trying to solve I expect someone here can come up with a better solution.

Community
  • 1
  • 1
Dave Webb
  • 179,733
  • 56
  • 298
  • 296
  • And how to make attributes callable? – paweloque Jun 24 '11 at 12:18
  • 2
    Thanks a lot! I wanted to know this not only because I need this for a specific problem, but also to understand python better. – paweloque Jun 24 '11 at 12:30
  • Does the "types.MethodType" call assign the function to the class permanently? – paweloque Jun 27 '11 at 14:09
  • It does not. It just makes a new method, `meth`, which _is_ an instance method of `SomeClass` (bound to `self`), but it doesn't change `myfunc` at all. Same as with `l=[3,5]`, `t=tuple(l)` doesn't change l at all. – Veky Jul 08 '15 at 09:48
6
def __getattr__(self, name):
  #return your function here...
Karoly Horvath
  • 88,860
  • 11
  • 107
  • 169
4
class FooBar:
    def __getattr__(self, name):
        def foo():
            print name
        return foo

a = FooBar()
a.helloThere()
Andrey Sboev
  • 6,774
  • 1
  • 17
  • 34