Here's an example of a toy trying to create a decorator that allows you to declare attribute names that must be required for parts of the "interface check" using the standard __subclasshook__ and __instancecheck__ .
It seems to work as expected when I decorate the Foo class. I am creating a Bar class that is not associated with Foo , but has the necessary attributes, and it correctly satisfies isinstance(instance_of_bar, Foo) == True .
But then, as another example, I make the dict subclass augmented so that key values โโare accessible with getattr syntax (for example, dict , where d['a'] can be replaced with da to get the same result). In this case, the attributes are instance attributes, so __instancecheck__ should work.
Here is the code. Note that, given that the example with the Bar instance works, selecting the โmonkeypatchโ function __subclasshook__ in the Foo class (which has a metaclass) works fine. Therefore, it does not seem that you need to define a function directly in the definition of a metaclass class.
#Using Python 2.7.3 import abc def interface(*attributes): def decorator(Base): def checker(Other): return all(hasattr(Other, a) for a in attributes) def __subclasshook__(cls, Other): if checker(Other): return True return NotImplemented def __instancecheck__(cls, Other): return checker(Other) Base.__subclasshook__ = classmethod(__subclasshook__) Base.__instancecheck__ = classmethod(__instancecheck__) return Base return decorator @interface("x", "y") class Foo(object): __metaclass__ = abc.ABCMeta def x(self): return 5 def y(self): return 10 class Bar(object): def x(self): return "blah" def y(self): return "blah" class Baz(object): def __init__(self): self.x = "blah" self.y = "blah" class attrdict(dict): def __getattr__(self, attr): return self[attr] f = Foo() b = Bar() z = Baz() t = attrdict({"x":27.5, "y":37.5}) print isinstance(f, Foo) print isinstance(b, Foo) print isinstance(z, Foo) print isinstance(t, Foo)
Print
True True False False
This is an example of a game - I'm not looking for a better way to implement my attrdict class. The Bar example demonstrates monkeypatched __subclasshook__ . The other two examples demonstrate __instancecheck__ failure for instances that have simple instance attributes to validate. In such cases, __instancecheck__ is not even called.
I can manually verify that the condition from my __instancecheck__ function is __instancecheck__ by the __instancecheck__ instance (that is, hasattr(instance_of_attrdict, "x") is True as needed) or z .
Again, it seems to work fine for the Bar instance. This suggests that __subclasshook__ correctly applied by the decorator and that fixing the custom __metaclass__ not a problem. But __instancecheck__ does not seem to be called in the process.
Why can __subclasshook__ be defined outside the metaclass class definition and added later, but not __instancecheck__ ?