Search code examples
pythonclassinheritancegetattributenew-style-class

Why does overriding __getattribute__ to proxy a value screw up isinstance?


Why does this happen?

class IsInstanceScrewer(object):
    def __init__(self, value):
        self.value = value

    def __getattribute__(self, name):
        if name in ('value',):
            return object.__getattribute__(self, name)
        value = object.__getattribute__(self, 'value')
        return object.__getattribute__(value, name)

isinstance(IsInstanceScrewer(False), bool) #True
isinstance(IsInstanceScrewer([1, 2, 3]), list) #True

The class is definitely not an instance of bool, even though it attempts to wrap it.


Solution

  • __getattribute__ is returning the __class__ of the wrapped value instead of its own __class__:

    >>> class IsInstanceScrewer(object):
        def __init__(self, value):
            self.value = value
    
        def __getattribute__(self, name):
            print name
            if name in ('value',):
                return object.__getattribute__(self, name)
            value = object.__getattribute__(self, 'value')
            return object.__getattribute__(value, name)
    
    >>> isinstance(IsInstanceScrewer(False), bool)
    __class__
    True
    >>> isinstance(IsInstanceScrewer([1, 2, 3]), list)
    __class__
    True
    

    This may be desired behavior or not depending on what you're doing.