<div dir="ltr"><div dir="ltr"><div dir="ltr"><div>Chris,</div><div><br></div><div>Yes, the following works:</div>"""<br>(Note that any object `x` is always considered to be an instance of<br>`type(x)`, and this cannot be overridden.)</div><div dir="ltr">"""</div><div dir="ltr"><br></div><div dir="ltr">
<div>NOTE:  I fixed your sentence of `x.__class__` to `type(x)` since it is not always true that `x.__class__ == type(x)`.</div><div><br></div><div>For example the actual code reference above:</div><div><br></div><div>
<div><a href="https://github.com/python/cpython/blob/master/Objects/abstract.c#L2397-L2405" target="_blank">https://github.com/python/cpython/blob/master/Objects/abstract.c#L2397-L2405</a></div><div><br></div><div>Says "<span class="gmail-m_7320602684269024792gmail-pl-k">if</span> (<span class="gmail-m_7320602684269024792gmail-pl-c1">Py_TYPE</span>(inst) == (PyTypeObject *)cls)" in the actual C Python implementation:</div><div><br></div><div>So it using `type(x)` not `x.__class__`</div></div>

</div><div dir="ltr"><br></div><div>Thanks,</div><div><br></div><div>Joy Diamond.</div><div><br></div><div><div>====</div><div><br></div><div>ADDENDUM:</div><div><br></div><div>Here is an example where `type(x) is not x.__class__`   (there are other not as perverse examples where you want `.__class__` to differ from `type`)<br></div><div><br></div><div>NOTE:  The final assert will fail, showing that `type(x) is not x.__class__`<br></div><div><br></div><div>#<br>#   This really perverse code demonstrates that `t.__class__` is *NOT*<br>#   always the same as type(t).</div><div>#</div><div>#  The code shows an metaclass that when you derive objects from its classes, creates a `7`</div><div>#  instead of a derived class.</div><div>#<br></div><div>def not_really_a_metaclass__make_a_7(name, bases, member):<br>    return 7<br><br>@property<br>def not_really_a_class__make_a_7(t):<br>    return not_really_a_metaclass__make_a_7<br><br>class Metaclass__Make_A_7(type):<br>    __class__ = not_really_a_class__make_a_7<br><br>Make_A_7 = Metaclass__Make_A_7('Make_A_7', ((object,)), {})<br><br><br>#<br>#   Now then:<br>#<br>#       `Make_A_7` is a class that when inherited from creates a '7' instead<br>#       of a class ... :(<br>#<br>#   Works for python 2 & pypy (not yet fixed to work for python 3)<br>#<br>class Seven(Make_A_7):  # Calls `Make_A_7.__class__('Seven, (('Make_A_7,)), {})` which returns `7`<br>    pass<br><br>print('Seven is: %s' % Seven)<br><br>assert isinstance(Make_A_7, Metaclass__Make_A_7)<br>assert Make_A_7.__class__ == Metaclass__Make_A_7   #  This will *FAIL* due to the perverse definition of `.__class__`<br></div>

</div></div></div><br><div class="gmail_quote"><div dir="ltr">On Sat, Oct 27, 2018 at 2:25 PM Chris Angelico <<a href="mailto:rosuav@gmail.com">rosuav@gmail.com</a>> wrote:<br></div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">On Sun, Oct 28, 2018 at 5:03 AM Joy Diamond <<a href="mailto:python.gem@gmail.com" target="_blank">python.gem@gmail.com</a>> wrote:<br>
><br>
> Greetings,<br>
><br>
> This is a request to fix the documentation for __instancecheck__.<br>
><br>
> Please add the following (please rewrite better than I can -- I am not good at explaining concepts in short sentences):<br>
><br>
> NOTE:  As an optimization, isinstance(object, classinfo) does NOT call classinfo.__instancecheck__(instance) when type(object) == classinfo.<br>
><br>
> Consider the following program:<br>
><br>
> class M(type):<br>
>     def __instancecheck__(m, t):<br>
>         print('instancecheck(%s, %s)' % (m, t))<br>
>         return False                                    #   LIE!<br>
><br>
> Test = M('Test', ((object,)), {})<br>
><br>
> something = Test()<br>
><br>
> print('Does *NOT* call __instancecheck__:')<br>
> print('isinstance(something, Test): %s' % isinstance(something, Test))<br>
<br>
Here's the passage in question, for reference:<br>
<br>
"""<br>
The following methods are used to override the default behavior of the<br>
isinstance() and issubclass() built-in functions.<br>
<br>
In particular, the metaclass abc.ABCMeta implements these methods in<br>
order to allow the addition of Abstract Base Classes (ABCs) as<br>
“virtual base classes” to any class or type (including built-in<br>
types), including other ABCs.<br>
"""<br>
<a href="https://docs.python.org/3/reference/datamodel.html#customizing-instance-and-subclass-checks" rel="noreferrer" target="_blank">https://docs.python.org/3/reference/datamodel.html#customizing-instance-and-subclass-checks</a><br>
<br>
Since it uses the word "override", I agree that it's not entirely<br>
correct. The implication of "override" is that you can completely<br>
replace the normal behaviour. In this case, you can change the<br>
behaviour of subclass testing (for instance, you can "disown" a<br>
subclass by denying that instances of it are instances of yourself),<br>
and of course, you can claim an object as an instance of a class it<br>
didn't directly inherit from (the way ABCs work), but you cannot fib<br>
about direct instances. I think the behaviour is close enough to<br>
accurate that it doesn't need major rewording; how about adding this<br>
parenthesis:<br>
<br>
"""<br>
(Note that any object `x` is always considered to be an instance of<br>
`x.__class__`, and this cannot be overridden.)<br>
"""<br>
<br>
Would that work?<br>
<br>
ChrisA<br>
_______________________________________________<br>
Python-ideas mailing list<br>
<a href="mailto:Python-ideas@python.org" target="_blank">Python-ideas@python.org</a><br>
<a href="https://mail.python.org/mailman/listinfo/python-ideas" rel="noreferrer" target="_blank">https://mail.python.org/mailman/listinfo/python-ideas</a><br>
Code of Conduct: <a href="http://python.org/psf/codeofconduct/" rel="noreferrer" target="_blank">http://python.org/psf/codeofconduct/</a><br>
</blockquote></div>