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

Pieter van Oostrum pieter-l at vanoostrum.org
Tue Nov 5 10:30:53 EST 2019


Chris Angelico <rosuav at gmail.com> writes:

> On Tue, Nov 5, 2019 at 5:43 PM dieter <dieter at handshake.de> wrote:
>> 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__".
>
> PEP 3119 is specifically about Python 3.0; I don't know how much, if
> any, was backported into Python 2.

Yes, it has been there since Python 2.6.

I looked in the implementation, and isinstance(inst, cls) first checks if the class of ins is cls, then the result is True.
There are a few other shortcut cases, and only at the end the __instancecheck__ method is called.

You can check this with the original example:

In [88]: class MA(type):
    ...:   def __instancecheck__(cls, inst):
    ...:     print "MA", cls, inst
    ...: 
    ...: class AM(list): __metaclass__ = MA
    ...: class AM2(AM): pass
    ...: 
    ...: am = AM2()

In [89]: isinstance(am, AM)
MA <class '__main__.AM'> []
Out[89]: False

It returns False because __instancecheck__ returns None

Same for Python3:

In [8]: class MA(type):
   ...:   def __instancecheck__(cls, inst):
   ...:     print ("MA", cls, inst)
   ...: 
   ...: class AM(list, metaclass = MA): pass
   ...: class AM2(AM): pass
   ...: 
   ...: am = AM2()

In [9]: isinstance(am, AM)
MA <class '__main__.AM'> []
Out[9]: False

-- 
Pieter van Oostrum <piet-l at vanoostrum.org>
WWW: http://pieter.vanoostrum.org/
PGP key: [8DAE142BE17999C4]


More information about the Python-list mailing list