On 10/27/2018 2:53 PM, Joy Diamond wrote:
Chris,

Yes, the following works:
"""
(Note that any object `x` is always considered to be an instance of
`type(x)`, and this cannot be overridden.)
"""

Open a doc issue on bugs.python.org with the problem, motivation, and proposed solution and it should get considered.

NOTE:  I fixed your sentence of `x.__class__` to `type(x)` since it is not always true that `x.__class__ == type(x)`.

For example the actual code reference above:

https://github.com/python/cpython/blob/master/Objects/abstract.c#L2397-L2405

Says "if (Py_TYPE(inst) == (PyTypeObject *)cls)" in the actual C Python implementation:

So it using `type(x)` not `x.__class__`

Thanks,

Joy Diamond.

====

ADDENDUM:

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

NOTE:  The final assert will fail, showing that `type(x) is not x.__class__`

#
#   This really perverse code demonstrates that `t.__class__` is *NOT*
#   always the same as type(t).
#
#  The code shows an metaclass that when you derive objects from its classes, creates a `7`
#  instead of a derived class.
#
def not_really_a_metaclass__make_a_7(name, bases, member):
     return 7

@property
def not_really_a_class__make_a_7(t):
     return not_really_a_metaclass__make_a_7

class Metaclass__Make_A_7(type):
     __class__ = not_really_a_class__make_a_7

Make_A_7 = Metaclass__Make_A_7('Make_A_7', ((object,)), {})


#
#   Now then:
#
#       `Make_A_7` is a class that when inherited from creates a '7' instead
#       of a class ... :(
#
#   Works for python 2 & pypy (not yet fixed to work for python 3)
#
class Seven(Make_A_7):  # Calls `Make_A_7.__class__('Seven, (('Make_A_7,)), {})` which returns `7`
     pass

print('Seven is: %s' % Seven)

assert isinstance(Make_A_7, Metaclass__Make_A_7)
assert Make_A_7.__class__ == Metaclass__Make_A_7   #  This will *FAIL* due to the perverse definition of `.__class__`

On Sat, Oct 27, 2018 at 2:25 PM Chris Angelico <ros...@gmail.com <mailto:ros...@gmail.com>> wrote:

    On Sun, Oct 28, 2018 at 5:03 AM Joy Diamond
    <python....@gmail.com
    <mailto:python....@gmail.com>> wrote:
     >
     > Greetings,
     >
     > This is a request to fix the documentation for __instancecheck__.
     >
     > Please add the following (please rewrite better than I can -- I
    am not good at explaining concepts in short sentences):
     >
     > NOTE:  As an optimization, isinstance(object, classinfo) does NOT
    call classinfo.__instancecheck__(instance) when type(object) ==
    classinfo.
     >
     > Consider the following program:
     >
     > class M(type):
     >     def __instancecheck__(m, t):
     >         print('instancecheck(%s, %s)' % (m, t))
     >         return False                                    #   LIE!
     >
     > Test = M('Test', ((object,)), {})
     >
     > something = Test()
     >
     > print('Does *NOT* call __instancecheck__:')
     > print('isinstance(something, Test): %s' % isinstance(something,
    Test))

    Here's the passage in question, for reference:

    """
    The following methods are used to override the default behavior of the
    isinstance() and issubclass() built-in functions.

    In particular, the metaclass abc.ABCMeta implements these methods in
    order to allow the addition of Abstract Base Classes (ABCs) as
    “virtual base classes” to any class or type (including built-in
    types), including other ABCs.
    """
    
https://docs.python.org/3/reference/datamodel.html#customizing-instance-and-subclass-checks

    Since it uses the word "override", I agree that it's not entirely
    correct. The implication of "override" is that you can completely
    replace the normal behaviour. In this case, you can change the
    behaviour of subclass testing (for instance, you can "disown" a
    subclass by denying that instances of it are instances of yourself),
    and of course, you can claim an object as an instance of a class it
    didn't directly inherit from (the way ABCs work), but you cannot fib
    about direct instances. I think the behaviour is close enough to
    accurate that it doesn't need major rewording; how about adding this
    parenthesis:

    """
    (Note that any object `x` is always considered to be an instance of
    `x.__class__`, and this cannot be overridden.)
    """

    Would that work?

    ChrisA
    _______________________________________________
    Python-ideas mailing list
    Python-ideas@python.org
    <mailto:Python-ideas@python.org>
    https://mail.python.org/mailman/listinfo/python-ideas
    Code of Conduct: http://python.org/psf/codeofconduct/



_______________________________________________
Python-ideas mailing list
Python-ideas@python.org
https://mail.python.org/mailman/listinfo/python-ideas
Code of Conduct: http://python.org/psf/codeofconduct/



--
Terry Jan Reedy


_______________________________________________
Python-ideas mailing list
Python-ideas@python.org
https://mail.python.org/mailman/listinfo/python-ideas
Code of Conduct: http://python.org/psf/codeofconduct/

Reply via email to