[Doc-SIG] Documenting "Magic" Methods

Edward Welbourne Edward Welbourne <eddy@chaos.org.uk>
Tue, 15 Aug 2000 20:19:34 +0100 (BST)


>>   I'm not sure it makes sense to document the __*__() methods
>> individually;
> Well, certainly __getitem__ makes sense without __setitem__ ...

*Implementing* magic methods individually is a separate matter from
*documenting* them individually.  Aside from (off the top of my head)
__init__ and __call__, the __*__ methods' generic specs (in the language
reference manual) completely specify how each method is called - the
interface by which the python engine implements assorted bits of
syntactic magic.

Given the generic spec, the __*__ methods are best documented by an
announcement, in the class doc-string, of which abstract interfaces the
class implements; the class doc-string is also the right place to
describe (the abstract form of) any local deviation from normality.
Inserting (.data where needed and) doc strings, I'd document your
example as:

class bar:
    """Wrapper class for values stored in foo's dictionary"""
    def __init__(self, value): self.value = value

class foo:
    """Mapping class using bar's packaging for values.

    Implements the get and set aspects of the mapping interface, wrapping its
    values using bar. """

    def __init__(self): self.data = {}
    def __getitem__(self, key): return self.data[key]
    def __setitem__(self, key, value): self.data[key] = bar(value)

Crucially, the doc-string for a __*__ method is the generic spec of what
(part of an) interface that method supports.

If a __*__ method deviates from its generic spec by so much that its
users need to read its doc-string before doing usual things, it's
breaking the python engine's syntactic magic.  This generally makes a
strong case for calling the method something else and not claiming to
implement an interface you don't really support.  Of course, the world
is full of exceptions; and the __*__'s doc-string is the natural place
to record the details of such deviancy (the overview having gone in the
class docstring).  If we all abstain from documenting normal __*__
methods, deferring to the reference manual's generic doc for that name,
the deviants will stand out, increasing our chances of (noticing and so)
Doing The Right Thing when we do run into them.

Ideally, I guess, docgen would document __init__ not as a method with
that name but as the call semantics of the class; and, likewise,
__call__ as that of instances.  Anyone think of any other __*__ which
vary enough to warrant having doc strings in the normal run of events ?

	Eddy.
--
# an occasionally useful tool:
class listBok:
    """Mapping whose entries are lists, defaulting empty.

    Setting an item in the dictionary appends the item to the relevant list.
    """
    def __init__(self): self.__bok = {}
    def __delitem__(self, key): del self.__bok[key]
    def __setitem__(self, key, value): self[key].append(value)

    def __getitem__(self, key):
        try: row = self.__bok[key]
        except KeyError: row = self.__bok[key] = []
        return row