146 votes

Comment documenter les attributs de classe en Python?

Je suis en train d'écrire une classe légère, dont les attributs sont destinés à être accessible au public, et que parfois remplacée dans certaines instances. Il n'y a aucune disposition dans le langage Python pour créer des docstrings pour les attributs de classe, ou pour tout autre type d'attributs, pour cette question. Qu'est-ce que la façon acceptée, doit y en avoir un, pour documenter ces attributs? Actuellement, je suis en train de faire ce genre de chose:

class Albatross(object):
    """A bird with a flight speed exceeding that of an unladen swallow.

    Attributes:
    """

    flight_speed = 691
    __doc__ += """
        flight_speed (691)
          The maximum speed that such a bird can attain.
    """

    nesting_grounds = "Raymond Luxury-Yacht"
    __doc__ += """
        nesting_grounds ("Raymond Luxury-Yacht")
          The locale where these birds congregate to reproduce.
    """

    def __init__(self, **keyargs):
        """Initialize the Albatross from the keyword arguments."""
        self.__dict__.update(keyargs)

Cela se traduira dans la classe de docstring contenant de la norme initiale docstring de la section, ainsi que les lignes ajoutées pour chaque attribut via augmentée cession __doc__.

Bien que ce style ne semble pas être expressément interdites dans la docstring lignes directrices de style, c'est pas mentionnée comme une option. L'avantage ici est qu'il fournit un moyen pour les attributs des documents aux côtés de leurs définitions, tout en créant une présentable classe docstring, et en évitant d'avoir à écrire des commentaires que réitérer les informations de la docstring. Je suis encore un peu ennuyé que j'ai d'écrire les attributs de deux fois; je suis envisage d'utiliser les représentations de chaîne de valeurs dans la docstring au moins d'éviter la duplication des valeurs par défaut.

Est-ce un odieux violation de l'ad hoc de la communauté des conventions? Est-il acceptable? Est-il un meilleur moyen? Par exemple, il est possible de créer un dictionnaire contenant des valeurs et des docstrings pour les attributs, puis ajouter le contenu de la classe __dict__ et docstring vers la fin de la déclaration de la classe; cela permettrait d'atténuer le besoin d'entrer les noms des attributs et des valeurs deux fois. edit: cette dernière idée est, je pense, pas possible, du moins pas sans dynamiquement la construction de l'ensemble de la classe à partir des données, ce qui semble être une très mauvaise idée, sauf si il y a une autre raison de le faire.

Je suis assez nouveau à python et encore de travailler sur les détails de style de codage, si peu en rapport avec les critiques sont aussi les bienvenues.

115voto

ʇsәɹoɈ Points 8284

Pour éviter toute confusion: le terme de propriété a un sens précis en python. De quoi vous parlez, c'est ce que nous appelons les attributs de classe. Depuis, ils sont toujours suivies par le biais de leur classe, je trouve que ça fait sens pour les documenter au sein de la classe' doc chaîne. Quelque chose comme ceci:

class Albatross(object):
    """A bird with a flight speed exceeding that of an unladen swallow.

    Attributes:
        flight_speed     The maximum speed that such a bird can attain
        nesting_grounds  The locale where these birds congregate to reproduce.
    """
    flight_speed = 691
    nesting_grounds = "Throatwarbler Man Grove"

Je pense que c'est beaucoup plus facile sur les yeux de l'approche dans votre exemple. Si je voulais vraiment une copie de l'attribut valeurs apparaissent dans la doc de la chaîne, je voudrais les mettre sur le côté ou en dessous de la description de chaque attribut.

Edit:

Gardez à l'esprit qu'en Python, doc chaînes sont les membres d'un objet document, et non pas simplement le code source des annotations. Depuis attribut de classe variables ne sont pas des objets eux-mêmes, mais des références à des objets, ils n'ont aucun moyen de tenir doc chaînes de caractères qui leur sont propres. Je suppose que vous pourriez faire un cas pour la doc des chaînes de références, peut-être de décrire "ce qu'il devrait aller ici" au lieu de "ce qui est fait ici", mais je trouve ça assez facile de le faire que dans la classe contenant la doc de la chaîne.

38voto

marcz Points 414

Vous citez le PEP257: Docstring Conventions, dans la section qu'est-Ce que une docstring , il est dit:

Les littéraux de chaîne est présente ailleurs dans le code Python peut également agir à titre de documentation. Ils ne sont pas reconnus par le bytecode Python compilateur et ne sont pas accessibles d'exécution comme les attributs de l'objet (c'est à dire pas affecté __doc__), mais les deux types d'extra docstrings peuvent être extraits par des outils logiciels:

Les littéraux de chaîne survenant immédiatement après une simple affectation à haut niveau d'un module de classe, ou de __init__ de la méthode sont appelés "attribut docstrings".

Et ceci est expliqué plus en détails dans la PPE 258: l'Attribut docstrings. Comme explique ci-dessus ʇsəɹoɈ. un attribut n'est pas un objet qui peut être propriétaire d'un __doc__, de sorte qu'ils n'apparaissent pas dans help() ou pydoc. Ces docstrings ne peut être utilisé pour la documentation générée.

Mais, actuellement, quelques outils à utiliser.

L'ancienne Epydoc ne les utiliser et le Sphinx de l'introduisit dans v0.6 et étendu dans v1.1. Sphinx pouvez utiliser docstring sur une ligne avant une cession ou un commentaire spécial à la suite d'une cession.

Voir la directive autoattribute dans le Sphinx Manuel et les exemples de l'attribut docstrings.

19voto

gerrit Points 1588

Vous pourriez abus de propriétés à cet effet. Propriétés contiennent un getter, setter, un deleter, et une docstring. Naïvement, ça ferait très détaillé:

class C:
    def __init__(self):
        self._x = None

    @property
    def x(self):
        """Docstring goes here."""
        return self._x

    @x.setter
    def x(self, value):
        self._x = value

    @x.deleter
    def x(self):
        del self._x

Ensuite, vous aurez une docstring appartenant à C. x:

In [24]: print(C.x.__doc__)
Docstring goes here.

Pour ce faire, pour un grand nombre d'attributs est lourd, mais vous pourriez envisager une fonction d'assistance myprop:

def myprop(x, doc):
    def getx(self):
        return getattr(self, '_' + x)

    def setx(self, val):
        setattr(self, '_' + x, val)

    def delx(self):
        delattr(self, '_' + x)

    return property(getx, setx, delx, doc)

class C:
    a = myprop("a", "Hi, I'm A!")
    b = myprop("b", "Hi, I'm B!")

In [44]: c = C()

In [46]: c.b = 42

In [47]: c.b
Out[47]: 42

In [49]: print(C.b.__doc__)
Hi, I'm B!

Ensuite, l'appel de Pythons interactive help donnera:

Help on class C in module __main__:

class C
 |  Data descriptors defined here:
 |  
 |  a
 |      Hi, I'm A!
 |  
 |  b
 |      Hi, I'm B!

which I think should be pretty much what you're after.

Edit: je me rends compte maintenant que nous pouvons peut-être vous éviter le besoin de passer le premier argument myprop , parce que le nom interne n'a pas d'importance. Si, à la suite des appels d' myprop peut en quelque sorte se communiquer les uns avec les autres, il pourrait décider automatiquement sur une longue et rare interne le nom de l'attribut. Je suis sûr qu'il y a des moyens à mettre en oeuvre, mais je ne sais pas si ils en valent la peine.

1voto

Je suggère d'utiliser des constructions Sphinx .

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X