17

I want to create a class that doesn't gives an Attribute Error on call of any method that may or may not exists:

My class:

class magic_class:
    ...
    # How to over-ride method calls
    ...

Expected Output:

ob = magic_class()
ob.unknown_method()
# Prints 'unknown_method' was called

ob.unknown_method2()
# Prints 'unknown_method2' was called

Now, unknown_method and unknown_method2 doesn't actually exists in the class, but how can we intercept the method call in python ?

martineau
  • 119,623
  • 25
  • 170
  • 301
Yugal Jindle
  • 44,057
  • 43
  • 129
  • 197
  • possible duplicate of [Intercept method calls in Python](http://stackoverflow.com/questions/2704434/intercept-method-calls-in-python) – jamylak Jun 04 '12 at 10:29
  • 3
    Side note FYI: PEP8 says it should be named like `class MagicClass:` and new style should at least inherit object probably: `class MagicClass(object):` – mVChr Jun 04 '12 at 10:29

3 Answers3

36

Overwrite the __getattr__() magic method:

class MagicClass(object):
    def __getattr__(self, name):
        def wrapper(*args, **kwargs):
            print "'%s' was called" % name
        return wrapper

ob = MagicClass()
ob.unknown_method()
ob.unknown_method2()

prints

'unknown_method' was called
'unknown_method2' was called
Sven Marnach
  • 574,206
  • 118
  • 941
  • 841
8

Just in case someone is trying to delegate the unknown method to an object, here's the code:

class MagicClass():
    def __init__(self, obj):
        self.an_obj = obj

    def __getattr__(self, method_name):
        def method(*args, **kwargs):
            print("Handling unknown method: '{}'".format(method_name))
            if kwargs:
                print("It had the following key word arguments: " + str(kwargs))
            if args:
                print("It had the following positional arguments: " + str(args))
            return getattr(self.an_obj, method_name)(*args, **kwargs)
        return method

This is super useful when you need to apply the Proxy pattern.

Moreover, considering both args and kwargs, allows you to generate an interface totally user friendly, as the ones that use MagicClass treat it as it was the real object.

onofricamila
  • 930
  • 1
  • 11
  • 20
2

Override __getattr__; see http://docs.python.org/reference/datamodel.html

LaC
  • 12,624
  • 5
  • 39
  • 38