Search code examples
pythonpython-3.xinheritancedocstring

What is the reason that child class does not inherit `__doc__` property/method?


I am a bit confused about the difference in behavior between __doc__ and other methods:

# python 3.10.13
class Parent:
    def __init__(self, doc):
        self._doc = doc

    def __doc__(self):
        return self._doc
    
    def __other__(self):
        return self._doc


class Child(Parent):
    pass


>>> print(Parent("test").__doc__())
test

>>> print(Child("test").__doc__)
None # TypeError if call __doc__() since it is not defined
>>> print(Child("test").__other__())
test

But it does not work as property either:

# python 3.10.13
class Parent:
    def __init__(self, doc):
        self._doc = doc

    @property
    def __doc__(self):
        return self._doc

    @property
    def __other__(self):
        return self._doc

class Child(Parent):
    pass


>>> print(Parent("test").__doc__)
test

>>> print(Child("test").__doc__)
None
>>> print(Child("test").__other__)
test

This is mentioned and somewhat discussed here @22750354, but I need help finding out why the Child class does not inherit the method/property of __doc__. And are there other methods like __doc__ in terms of inheritance? Thank you.


Solution

  • As a first approximation1, when you write

    obj.a
    

    Python attempts to lookup a by

    1. checking whether obj has an attributed named a, then
    2. checking whether obj's class (obj.__class__) has an attribute a, then
    3. recursively checking each parent class (obj.__class__.__mro__) for an attribute a.

    If at any point, an attribute named a is found, that then that object gets returned as the result. This is what is inheritance means in Python. Child classes don't copy their parents, they just delegate attribute lookups to them.

    Now, whenever you define a class as

    class Child(Parent):
        ...
    

    that class object always gets assigned a __doc__ attribute: the docstring if one was provided, or None otherwise.

    >>> Child.__doc__ is None
    True
    

    Because of this, any lookups for the attribute __doc__ will only ever propagate up to the class level before a matching object is found. Attribute lookup will never reach the stage of checking the parent classes.

    1The complete attribute lookup process is much more complicated. See 3.3.2. Customizing attribute access from the Python Data Model docs for the bigger picture.