1

Well, I love Python, but find mainly two things annoying: self and docstrings below declarations.

What I would like to know is, how should I be able to have my docstrings before the declarations in my code? Something like:

"""Class docstring"""
class MyClass(object):
    "Method documentation"
    def my_method(self):
        pass

Perhaps using some form of decorator?

2
  • A valid answer if there is some tool to extract the documentation correctly. :) Commented Jan 18, 2012 at 18:45
  • 7
    You would be doing yourself a favor to work with the grain of Python and not fight its design. Just sayin ;-) Commented Jan 18, 2012 at 18:46

4 Answers 4

3

It is possible to write a decorator that sets the __doc__ property:

def doc(docstr):
    def deco(f):
        f.__doc__ = docstr
        return f
    return deco

This will work for functions and old-style classes, but not for new-style classes, since the __doc__ attribute of new-style classes is read-only (unless you use metaclasses, adding even more complexity for very little gain).

I'd recommend against using such a decorator anyway. Just stick to the usual conventions. That way, fellow developers will immediately understand what's a docstring, tools parsing the source code for docstrings will work correctly etc.

Edit: To also cover new-style classes, you could use this implementation:

def doc(docstr):
    def deco(f):
        if isinstance(f, type):
            d = vars(f).copy()
            d["__doc__"] = docstr
            return type(f.__name__, f.__bases__, d)
        f.__doc__ = docstr
        return f
    return deco

Since __doc__ is read-only, we need to create a new type object with the desired documentation. For simplicity, I don't consider custom metaclasses (if you want to, replace type by f.__class__ in the above code).

Again, I don't recommend using this decorator.

Sign up to request clarification or add additional context in comments.

7 Comments

Very well. I was curious if an easy solution was possible, but it will damage communicaton, as said by everyone. :) I will try to abide by the conventions for communication's sake. Thanks.
There is no problem assigning new-style class __doc__ in python 2.7.2 for me.
@SvenMarnach: Apparently Django classes, although new-style classes, can have their __doc__. I didn't realise this was the exception to the rule.
@Marcin: I just found out that any metaclass written in Python will make __doc__ writable, even if it's simply class Meta(type): pass. So in the end it wasn't the full truth when I stated that the decorator does not work for new-style classes.
In Python 3.3 __doc__ is writable again.
|
2

As you already suggest in your question, you could do something as follows:

from functools import wraps

def docstring(docstr):
    def decorator(cls):
        @wraps(cls)
        def wrapper(*args, **kwargs):
            return cls(*args, **kwargs)
        wrapper.__doc__ = docstr
        return wrapper
    return decorator

@docstring("""Class docstring""")
class MyClass(object):
    def my_method(self):
        pass

print MyClass.__doc__   # Class docstring

However, I don't find this particularly better than the current syntax.

5 Comments

This has the disavantage of turning MyClass into a function. The representation will be something like <function __main__.MyClass>, and you lose access to special attributes like __base__ etc.
Will that have impact in any type identification function?
@ThiagoChaves: Do you mean isinstance()? This won't work any more, neither will it be possible at all to derive from a class with such a decorator. In the end, this decorator might be completely unusable.
@Sven: True. This is unfortunately a deal breaker. So, out of curiosity, is there any way to also cover new-style classes and retain their full capabilities?
@ThiagoChaves: Yes, that's possible, but ugly. I'll add an implementation to my answer.
1

That will not work. A docstring, is by definition, a string on the line following the declaration.

If you really want to do this with a decorator, you can create a decorator that sets the __doc__ property of the wrapped function (or class).

Comments

-1

If you really want to, sure.

def doc(text):
  def w(f):
    f.__doc__ = text
    return f
  return w

4 Comments

Nice and simple, but as Sven said, does not work on new style classes.
@Ignacio: Yes, it will work on functions. Just complete the "return w" after the last line. Without it, launches an exception. Edit: ok, I saw the correction now. As a side note, I didn't downvote it.
@ThiagoChaves: Testing shows me that there is no problem assigning to __doc__ of new-style classes
@Marcin: I tried in my CPython 2.6 interpreter on Ubuntu and it didn't work. Also, Sven shows some evidence in his answer's comment.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.