This issue tracker has been migrated to GitHub, and is currently read-only.
For more information, see the GitHub FAQs in the Python's Developer Guide.

classification
Title: Isinstance() behavior is not consistent with the document
Type: behavior Stage: resolved
Components: Documentation, Interpreter Core Versions: Python 3.8, Python 3.7
process
Status: closed Resolution: not a bug
Dependencies: Superseder:
Assigned To: docs@python Nosy List: docs@python, hongweipeng, terry.reedy
Priority: normal Keywords:

Created on 2018-05-03 10:30 by hongweipeng, last changed 2022-04-11 14:59 by admin. This issue is now closed.

Messages (2)
msg316118 - (view) Author: hongweipeng (hongweipeng) * Date: 2018-05-03 10:30
In the PEP 3119(https://www.python.org/dev/peps/pep-3119/),it introduce about Customizing instance and subclass checks.

>The primary mechanism proposed here is to allow overloading the built-in functions isinstance() and issubclass(). The overloading works as follows: The call isinstance(x, C) first checks whether C.__instancecheck__ exists, and if so, calls C.__instancecheck__(x) instead of its normal implementation.


but my code doesn't works.
```
class Sizeable(object):
    def __instancecheck__(cls, instance):
        print("__instancecheck__ call")
        return hasattr(instance, "__len__")

class B(object):
    pass

b = B()
print(isinstance(b, Sizeable)) # output:False
```
The __instancecheck__ function  is not called. In PyObject_IsInstance,when isinstance(x, C) the following three conditions are reached, __instancecheck__ will take effect:
1. x can not be directly instantiated by C;

2. The C class specifies the metaclass;

3. The __instancecheck__ in the specified metaclass class is defined.

This code can work:
```
class MetaSizeable(type):
    def __instancecheck__(cls, instance):
        print("__instancecheck__ call")
        return hasattr(instance, "__len__")

class Sizeable(metaclass=MetaSizeable):
    pass

class B(object):
    pass

b = B()
print(isinstance(b, Sizeable))  # output: False
print(isinstance([], Sizeable)) # output: True
```

So,the problem is that the document does not conform to the reality.Can it be guaranteed that __instancecheck__  is always called?

If yes: PyObject_IsInstance should be tweaked.
If no:  document should be tweaked.
msg316186 - (view) Author: Terry J. Reedy (terry.reedy) * (Python committer) Date: 2018-05-04 21:42
https://docs.python.org/3/reference/datamodel.html#customizing-instance-and-subclass-checks
says
"Note that these methods are looked up on the type (metaclass) of a class. They cannot be defined as class methods in the actual class. This is consistent with the lookup of special methods that are called on instances, only in this case the instance is itself a class."

IE, your first example is documented as wrong.  Your second example, which works, follows the example in
https://docs.python.org/3/reference/datamodel.html#customizing-instance-and-subclass-checks
History
Date User Action Args
2022-04-11 14:59:00adminsetgithub: 77598
2018-05-04 21:42:38terry.reedysetstatus: open -> closed

versions: + Python 3.8
nosy: + terry.reedy

messages: + msg316186
resolution: not a bug
stage: resolved
2018-05-03 10:30:05hongweipengcreate