Search code examples
pythondecoratorisinstance

Making 'isinstance' work with decorators


How does the Python isinstance function work internally? Is there anything I can do to alter its results, like define a special function inside a class or something? Here's my use case:

class Decorator:
    def __init__(self, decorated):
        self._decorated = decorated

    def __call__(self):
        return self._decorated()

@Decorator
class Foo:
    pass

f = Foo()

# How can I make this be true?
isinstance(f, Foo)

Decorator acts almost like a mixin, except a mixing wouldn't be appropriate here. Is there any way I can make the above code work? I should also note that the isinstance line also gives the following error:

    isinstance(f, Foo)
TypeError: isinstance() arg 2 must be a type or tuple of types


Solution

  • How about the following:

    def Decorator(decorated):
        class Dec(decorated):
            def __call__(self):
                print 'in decorated __call__'
                return decorated.__call__(self)
        return Dec
    
    @Decorator
    class Foo(object):
        def __call__(self):
            print 'in original __call__'
    
    f = Foo()
    
    # How can I make this be true?
    print isinstance(f, Foo)
    

    With the above code:

    • isinstance(f, Foo) works;
    • f() calls the decorated method which then forwards to the original method.

    The basic idea is to make sure that the decorated Foo is still a class, and to also make sure that the decorated Foo is a subclass of the original Foo.

    P.S. The purpose of all this is not entirely clear to me; it might be that metaclasses are a better way to achieve what you're trying to do.