3

Consider the code:

class MyClass(object):
  '''
  Keep track of file and its path on disk
  '''

  def __init__(self):
    self.file = None
    self.path = None

I'd like to add doc-string to all properties. So, I could do something like (for file property):

class MyClass(object):
  ...

  @property
  def file(self):
    '''
    this is a doc-string for file property
    '''

    return self._file

  @file.setter
  def file(self, value):
    self._file = value

  @file.deleter
  def file(self):
    del self._file

However, it is tedious to write getter, setter and deleter methods for each property. In fact, these methods (as it is seen above) do the default job.

Is there an easy way to only add doc-string to properties?

Samvel
  • 182
  • 2
  • 6

5 Answers5

2

Well, you can always create your own descriptor that allows documentation and implements other operations in the standard way:

class DocProperty(object):

    def __init__(self, doc=None):
        self._values = {}
        self.__doc__ = doc

    def __get__(self, obj, objtype=None):
        if obj is None:
            return self
        return self._values[obj]

    def __set__(self, obj, value):
        self._values[obj] = value

    def __delete__(self, obj):
        del self._values[obj]

You would then use it like this:

class SomeClass(object):

    p1 = DocProperty('some docs')

print SomeClass.p1.__doc__
# some docs
c = SomeClass()
c.p1 = 2
print c.p1
# 2
del c.p1

Personally, though, I think it's overkill. If you need it for the code, use comments in the constructor. All automatic documentation generators also support commenting simple Python attributes in some way.

Dzinx
  • 55,586
  • 10
  • 60
  • 78
  • This implementation is broken: if you create two instances of SomeClass, then their p1 properties will share values -- change one instance and the other instance's property will change. – Edward Loper Feb 15 '12 at 15:48
  • @EdwardLoper: Thanks, you're right! I knew I missed something when I saw I don't need the `obj` argument. I corrected the implementation. I could've done it the other way around (i.e. to keep values in the objects themselves instead of in a common dictionary), but then the user would have to provide a variable name as the second argument to `DocProperty`. Still, it's not as clean now as I'd like it to be. – Dzinx Feb 15 '12 at 21:07
  • your (fixed) implementation has some issues with non-hashable obj's, and with pickling. The first could be fixed by hasing on id(obj) rather than just obj. The second would be harder to fix, but whether that's important depends on whether these objects will ever get pickled. – Edward Loper Feb 16 '12 at 14:29
  • @EdwardLoper: yeah, and then there are some more problems when these objects are modified in concurrent threads, etc. It's more like a proof-of-concept, anyway. I can't think of any reasonable use case for it. – Dzinx Feb 17 '12 at 13:31
1

This is a fixed version of DzinX's DocProperty class:

class DocProperty(object):

    def __init__(self, name, doc):
        self._name = '_'+name
        self.__doc__ = doc

    def __get__(self, obj, objtype=None):
        if obj is None:
            return self
        return getattr(obj, self._name)

    def __set__(self, obj, value):
        setattr(obj, self._name, value)

    def __delete__(self, obj):
        delattr(obj, self._name)

Usage:

class SomeClass(object):
    p1 = DocProperty('p1', 'some docs')

Note that using this will make your code less efficient though -- every attribute access becomes more expensive. But I guess that in some contexts the ability to add docs might be worth it (esp if efficiency isn't a concern in your context).

Edward Loper
  • 15,374
  • 7
  • 43
  • 52
0

Did you mean attributes (defined in init at the start of the question) or properties, as stated?

For properties just put the doc string in the getter. You can access it like my_class_instance.__class__.file.__doc__.

Using an IDE like PyCharm can help create properties for you. In PyCharm you just start typing "prop" and a pop-up will help you create the full template for read-only properties, read/write, etc.

Rafe
  • 1,937
  • 22
  • 31
0

Not sure if you're searching for that, but if you're using Sphinx for your documentation system, you can put property doc with this syntax:

class MyClass(object):
  '''
  Keep track of file and its path on disk
  '''

  def __init__(self):
    #: this is doc for file
    self.file = None

    #: this is the documentation for path
    #: on multiple line too.
    self.path = None
tito
  • 12,990
  • 1
  • 55
  • 75
0

If you're generating API docs using a tool like epydoc (which generates a webpage describing the API of your code), then you can use variable docstrings. But if you want the docstrings to be available for interactive/reflective use, then DzinX's answer is probably the way to go.

Edward Loper
  • 15,374
  • 7
  • 43
  • 52