Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to intercept a method call which doesn't exist?

Tags:

python

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 ?

like image 916
Yugal Jindle Avatar asked Jun 04 '12 10:06

Yugal Jindle


2 Answers

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
like image 88
Sven Marnach Avatar answered Sep 26 '22 12:09

Sven Marnach


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.

like image 25
onofricamila Avatar answered Sep 25 '22 12:09

onofricamila