Jak udokumentować atrybuty klas w Pythonie? [zamknięte]

zamknięte . To pytanie jest oparte na opinii. Obecnie nie przyjmuje odpowiedzi.

Chcesz poprawić to pytanie? zaktualizuj pytanie, aby mogło być odpowiedź z faktami i cytatami przez edytując ten post .

Zamknięte 2 lata temu .

Popraw to pytanie

Piszę lekką klasę, której atrybuty mają być publicznie dostępne i tylko czasami nadpisywane w określonych instancjach. Nie ma przepisu w Język Python do tworzenia docstringów dla atrybutów klasy, lub dowolnego rodzaju atrybutów. Jaki jest oczekiwany i wspierany sposób dokumentowania tych atrybutów? Obecnie robię tego typu rzeczy:

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)

Spowoduje to, że docstring klasy będzie zawierał początkową standardową sekcję docstring, a także linie dodane dla każdego atrybutu poprzez rozszerzone przypisanie do __doc__.

Chociaż ten styl nie wydaje się być wyraźnie zabronione w docstring style guidelines , nie jest również wymienione jako opcja. Zaletą jest to, że zapewnia sposób dokumentowania atrybutów wraz z ich definicjami, jednocześnie tworząc reprezentowalną klasę docstring i unikając konieczności pisania komentarzy, które powtarzają informacje z docstring. Nadal jestem trochę zirytowany, że muszę faktycznie napisać atrybuty dwa razy; rozważam użycie reprezentacji łańcuchów wartości w docstringu do at należy unikać powielania wartości domyślnych.

Czy jest to ohydne naruszenie konwencji wspólnoty ad hoc? W porządku? Jest lepszy sposób? Na przykład, możliwe jest utworzenie słownika zawierającego wartości i docstringi dla atrybutów, a następnie dodanie zawartości do klasy __dict__ i docstring pod koniec deklaracji klasy; zmniejszyłoby to konieczność dwukrotnego wpisywania nazw atrybutów i wartości. edit : ten ostatni pomysł to chyba nie możliwe, przynajmniej nie bez dynamicznego budowania całej klasy z danych, co wydaje się naprawdę złym pomysłem, chyba że jest jakiś inny powód, aby to zrobić.

Jestem całkiem nowy w Pythonie i nadal pracuję nad szczegółami stylu kodowania, więc mile widziane są również niepowiązane krytyki.

Author: NeilG, 2010-06-16

3 answers

Aby uniknąć nieporozumień: termin Właściwość ma szczególne znaczenie w Pythonie. To, o czym mówisz, nazywamy atrybuty klasy. Ponieważ są one zawsze obsługiwane przez ich klasę, uważam, że sensowne jest dokumentowanie ich w ciągu Doc klasy. Coś takiego:

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"
Myślę, że to dużo łatwiejsze dla oczu niż podejście w twoim przykładzie. Jeśli naprawdę chciałem, aby Kopia wartości atrybutu pojawiła się w dokumencie string, chciałbym umieścić je obok lub poniżej opisu każdego atrybutu.

Należy pamiętać, że w Pythonie ciągi dokumentów doc są rzeczywistymi członkami obiektów, które dokumentują, a nie tylko adnotacjami do kodu źródłowego. Ponieważ zmienne atrybutów klasy nie są same w sobie obiektami, ale odwołaniami do obiektów, nie mają możliwości posiadania własnych łańcuchów doc. Wydaje mi się, że można by zrobić przypadek dla ciągów doc na odniesienia, być może opisać "co powinno iść tutaj "zamiast" co jest w rzeczywistości tutaj" , ale ja łatwo jest to zrobić w łańcuchu zawierającym klasę doc.

 94
Author: ʇsәɹoɈ,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-07-08 22:45:42

Cytujesz konwencje PEP257: Docstring, w sekcji Co to jest docstring jest napisane:

Literały łańcuchowe występujące gdzie indziej w kodzie Pythona mogą również działać jako dokumentacja. Nie są rozpoznawane przez kompilator kodu bajtowego Pythona i nie są dostępne jako atrybuty obiektu uruchomieniowego( tzn. nie są przypisane do _ _ doc__), ale dwa typy dodatkowych docstringów mogą być wyodrębniane przez narzędzia programowe:

Literały ciągów występujące bezpośrednio po prostym zadaniu na najwyższy poziom modułu, klasy lub metody __init _ _ są nazywane "docstrings atrybutu".

I jest to wyjaśnione bardziej szczegółowo w PEP 258: attribute docstrings. Jak wyjaśniono powyżej. atrybut nie jest obiektem, który może posiadać _ _ doc__, więc nie pojawi się w help() lub pydoc. Te docstringi mogą być używane tylko do generowanej dokumentacji.

Są używane w Sphinx z dyrektywą autoattribute

Sphinx może używać komentarzy w linii przed przypisaniem lub specjalny komentarz po przypisaniu lub docstring po definicji, która będzie autodokumentowana.

 33
Author: marcz,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2020-06-20 09:12:55

W tym celu można nadużywać właściwości. Właściwości zawierają getter, setter, deleter, i docstring . Naiwnie, to byłoby bardzo gadatliwe:

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

Wtedy będziesz miał docstring należący do C. x:

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

Zrobienie tego dla wielu atrybutów jest kłopotliwe, ale można wyobrazić sobie funkcję pomocniczą 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!

Wtedy wywołanie Pythons interactive help da:

Help on class C in module __main__:

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

Który myślę, że powinien być prawie tym, czym jesteś po.

Edit : teraz zdaję sobie sprawę, że być może możemy uniknąć konieczności przekazywania pierwszego argumentu myprop w ogóle, ponieważ wewnętrzna nazwa nie ma znaczenia. Jeśli kolejne wywołania myprop mogą w jakiś sposób komunikować się ze sobą, może automatycznie zdecydować się na długą i nieprawdopodobną wewnętrzną nazwę atrybutu. Jestem pewien, że istnieją sposoby, aby to wdrożyć, ale nie jestem pewien, czy są tego warte.

 15
Author: gerrit,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2019-04-09 14:16:24