__instancecheck__ metaclasses, how do they work: why do I get True when I tuple, why doesn't print run?

Rhodri James rhodri at kynesim.co.uk
Mon Nov 4 09:10:06 EST 2019


On 04/11/2019 11:30, Veek M wrote:
> 1. Why do I get True whenever i tuple the
> isinstance(f, (Bar, Foo))
> (and why don't the print's run)

I'm not very familiar with metaclasses, but I can answer the second part 
of your question.

> 
> 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


Aha.  You're trying to fix up the metaclass after the fact, which is not 
the right way to do it.  If you change the class definitions to:

class Foo(list, metaclass=MyzMeta):
     pass

class Bar(Foo, Miaow, metaclass=MyMeta):
     pass

then you get the prints from MyMeta.__instancecheck__().  The 
isinstance() still returns True, though, and I don't know why.  Then 
again, your definition of MyMeta is really weird.

> 
> 
> f = Foo()
> b = Bar()
> 
> print(isinstance(f, (Bar, Foo)))


-- 
Rhodri James *-* Kynesim Ltd


More information about the Python-list mailing list