From 7bc25ec7276db2a81e7823671a74eeb8aa6b4542 Mon Sep 17 00:00:00 2001 From: Raymond Hettinger Date: Mon, 5 Apr 2021 12:48:24 -0700 Subject: bpo-20503: Show how isinstance() works with ABC registered classes. (GH-25175) --- Doc/faq/programming.rst | 35 +++++++++++++++++++++++++++++++++++ 1 file changed, 35 insertions(+) diff --git a/Doc/faq/programming.rst b/Doc/faq/programming.rst index 93ffd36..514ca04 100644 --- a/Doc/faq/programming.rst +++ b/Doc/faq/programming.rst @@ -1420,6 +1420,41 @@ single class, e.g. ``isinstance(obj, (class1, class2, ...))``, and can also check whether an object is one of Python's built-in types, e.g. ``isinstance(obj, str)`` or ``isinstance(obj, (int, float, complex))``. +Note that :func:`isinstance` also checks for virtual inheritance from an +:term:`abstract base class`. So, the test will return ``True`` for a +registered class even if hasn't directly or indirectly inherited from it. To +test for "true inheritance", scan the :term:`MRO` of the class: + +.. testcode:: + + from collections.abc import Mapping + + class P: + pass + + class C(P): + pass + + Mapping.register(P) + +.. doctest:: + + >>> c = C() + >>> isinstance(c, C) # direct + True + >>> isinstance(c, P) # indirect + True + >>> isinstance(c, Mapping) # virtual + True + + # Actual inheritance chain + >>> type(c).__mro__ + (, , ) + + # Test for "true inheritance" + >>> Mapping in type(c).__mro__ + False + Note that most programs do not use :func:`isinstance` on user-defined classes very often. If you are developing the classes yourself, a more proper object-oriented style is to define methods on the classes that encapsulate a -- cgit v0.12