Diamond
Diamond

Reputation: 598

How to document a parameter that appears in more than function in Python?

Suppose that I have three functions a, b, and c. The way a is defined and documented is like this:

def a(a1, a2, p1="a", p2="b", p3=3):
  """
  :param a1:
  :param a2:
  :param p1: blah
  :param p2: blah blah
  :param p3: blah blah blah
  """

Now, functions b and c are defined is like this:

def b(b1, p1="a", p2="b", p3=3):
  ...
  return a(a1, a2, p1, p2, p3)

def c(c1, c2, c3, p1="a", p2="b", p3=3):
  ...
  b(b1, p1, p2, p3)
  ...

Clearly, parameters p1, p2, and p3 have the same definitions in all of these functions. How should these parameters be properly documented? Should the definition document be copied in all of these functions? In that case, if a definition needs to be changed, it has to be changed in all of these functions, which is kind of not easy to maintain.

Upvotes: 0

Views: 220

Answers (2)

sinback
sinback

Reputation: 1004

This is a matter of taste, so it's one of those SO posts that someone might fairly say is hard to answer / doesn't belong, etc.

I can't tell you how to organize your documentation, but I agree that it is a pain to keep docstrings with identical content up-to-date with one another. I would not choose to do that.

Here's a suggestion which does not answer your question, but which I hope to be useful anyway: I think that the pain of writing this documentation indicates a probable code smell in your project. If you're doing the same thing with something commonly, (here, using p1, p2, and p3 the same way), it's pretty likely that it makes sense to combine those things into one somehow. For example, if p1, p2, p3 were all just simply strings and ints, you could try putting them together into a NamedTuple or a dataclass or something.

(If you are feeling very philosophical about this stuff, you could also think about the dependency injection pattern, which is also often useful in situations like this. That might be a good thing to think about if your example is actually pared-down and p1, p2, and p3 are actually stooges for something more complicated.)

Upvotes: 0

duckboycool
duckboycool

Reputation: 2455

You can use a decorator factory to make this possible along with the __doc__ attribute, although it is a bit weird on syntax.

Here's the decorator.

def docadd(doc):
    def docaddfactory(func):
        if func.__doc__ is None:
            func.__doc__ = ''
        
        func.__doc__ += doc #Could also add a separator between current and added doc.
        
        return func
    
    return docaddfactory

Then from there, you could decorate functions with a variable input.

@docadd(shared_desc)
def b(b1, p1="a", p2="b", p3=3):
  ...
  return a(a1, a2, p1, p2, p3)

Upvotes: 1

Related Questions