Veek M <v...@dont-use-this.com> writes: I simplify your code to demonstrate what goes on: >>> class MA(type): ... def __instancecheck__(cls, inst): ... print "MA", cls, inst ... >>> class AM(list): __metaclass__ = MA ... >>> am = AM() >>> isinstance(am, AM) True
As you can see, even with a class (rather than a tuple) as second argument to "isinstance", "MA.__instancecheck__" is not called. I suppose that "isinstance" (at least under Python 2) does not behave exactly as stated in PEP 3119. Instead, "isinstance" first directly checks for the instance to be an instance of the class *AND ONLY IF THIS FAILS* calls the class' "__instancecheck__". As PEP 3119 suggests, "__instancecheck__" has been introduced to support abstract base classes. The example given there is an abstract base class "Sequence" and concrete derived classes "list" and "tuple". For this use case, it is okay when "isinstance(inst, cls)" returns "True" whenever "inst" is a "cls" object and that "cls.__instancecheck__" is used only to result in "True" also for other cases. > 1. Why do I get True whenever i tuple the > isinstance(f, (Bar, Foo)) > (and why don't the print's run) > > The docs say that you can feed it a tuple and that the results are OR'd > > ---- > The form using a tuple, isinstance(x, (A, B, ...)), is a shortcut for > isinstance(x, A) or isinstance(x, B) or ... (etc.). > ----- > which implies that the metaclasses are called for each class? > > > class MyzMeta(type): > def __instancecheck__(cls, other): > print('MyzzzzzzMeta', other) > return 0 > > > class MyMeta(MyzMeta, object): > def __instancecheck__(cls, other): > print('MyMeta') > print(cls, other) > return 0 > > > class Foo(list): > __metaclass__ = MyzMeta > pass > > class Miaow(object): > pass > > class Bar(Foo, Miaow): > __metaclass__ = MyMeta > pass > > > f = Foo() > b = Bar() > > print(isinstance(f, (Bar, Foo))) > raise SystemExit > > if isinstance(f, (Bar, Foo)): > print('success') -- https://mail.python.org/mailman/listinfo/python-list