Search code examples
pythonmethod-invocation

Can I create an object that receives arbitrary method invocation in python?


In python, can I create a Class that, when instantiated, can receive arbitrary method invocation? I have read this but couldn't put the pieces together

I guess it has something to do with the attribute lookup. For a class Foo:

class Foo(object):
  def bar(self, a):
    print a

The class attribute can be obtained by print Foo.__dict__, which gives

{'__dict__': <attribute '__dict__' of 'Foo' objects>, '__weakref__': <attribute '__weakref__' of 'Foo' objects>, '__module__': '__main__', 'bar': <function bar at 0x7facd91dac80>, '__doc__': None}

So this code is valid

foo = Foo()
foo.bar("xxx")

If I call foo.someRandomMethod(), AttributeError: 'Foo' object has no attribute 'someRandomMethod' would be resulted.

I want foo object to receive any random invocations and defaults to no-op, ie.

def func():
    pass

How can I achieve this? I want this behaviour to mock an object for testing.


Solution

  • From http://rosettacode.org/wiki/Respond_to_an_unknown_method_call#Python

    class Example(object):
        def foo(self):
            print("this is foo")
        def bar(self):
            print("this is bar")
        def __getattr__(self, name):
            def method(*args):
                print("tried to handle unknown method " + name)
                if args:
                    print("it had arguments: " + str(args))
            return method
    
    example = Example()
    
    example.foo()        # prints “this is foo”
    example.bar()        # prints “this is bar”
    example.grill()      # prints “tried to handle unknown method grill”
    example.ding("dong") # prints “tried to handle unknown method ding”
                         # prints “it had arguments: ('dong',)”