Jak udokumentować metodę za pomocą parametrów?

139

Jak udokumentować metody z parametrami przy użyciu ciągów dokumentacji Pythona?

EDYCJA: PEP 257 podaje ten przykład:

def complex(real=0.0, imag=0.0):
    """Form a complex number.

    Keyword arguments:
    real -- the real part (default 0.0)
    imag -- the imaginary part (default 0.0)

    """
    if imag == 0.0 and real == 0.0: return complex_zero
    ...

Czy jest to konwencja używana przez większość programistów Pythona?

Keyword arguments:
<parameter name> -- Definition (default value if any)

Spodziewałem się czegoś bardziej formalnego, np

def complex(real=0.0, imag=0.0):
    """Form a complex number.

    @param: real The real part (default 0.0)
    @param: imag The imaginary part (default 0.0)

    """
    if imag == 0.0 and real == 0.0: return complex_zero
    ...

Środowisko : Python 2.7.1

David Andreoletti
źródło
1
Czy przeczytałeś PEP 257? python.org/dev/peps/pep-0257
NPE
1
Istnieje kilka „standardów”, ale z praktycznego punktu widzenia, a zwłaszcza jeśli lubisz coś formalnego, polecam Sphinx . Integracja z Pycharm sprawia, że ​​generowanie dobrze skonstruowanych dokumentów jest raczej bezbolesne. IMHO
jojo

Odpowiedzi:

86

Na podstawie mojego doświadczenia wynika, że NumPy konwencje docstring (PEP257 rozszerzeniem) są najpowszechniej rozprzestrzeniania następnie konwencje, które są również wspierane przez narzędzia, takie jak Sfinks .

Jeden przykład:

Parameters
----------
x : type
    Description of parameter `x`.
Vladimir Keleshev
źródło
2
To jest bliżej tego, czego się spodziewałem. Niestety wybrałem zwykły PEP 257 i dodałem własną konwencję (kosztem utraty automatycznie generowanej dokumentacji HTML / PDF). Jednak następnym razem wybiorę to rozwiązanie. Dzięki.
David Andreoletti,
5
Kiedy próbuję przetworzyć twój sugerowany dokument, Sfinks narzeka SEVERE: Unexpected section title- czy znasz jakiś sposób, aby Sfinks był z tego szczęśliwszy?
Brandon Rhodes
@BrandonRhodes ten link mówi o używaniu tych konwencji ze Sphinx: github.com/numpy/numpy/blob/master/doc/HOWTO_DOCUMENT.rst.txt
Vladimir Keleshev
3
Właściwie wcześniej brakuje miejsca Description. Sprawdziłem dokumentację numpy, ponieważ od razu zauważyłem i pomyślałem: „Poczekaj chwilę, dlaczego to trzy spacje? To dziwne. Kto użyłby trzech spacji?”
Zelphir Kaltstahl
6
To mogła być najlepsza odpowiedź w momencie, gdy zadawano to pytanie, ale myślę, że od teraz (koniec 2017 r.) Sphinx wyszedł zwycięsko.
Alex L
120

Ponieważ ciągi dokumentacyjne są dowolne, tak naprawdę zależy to od tego, czego używasz do analizowania kodu w celu wygenerowania dokumentacji API.

Poleciłbym zapoznać się ze znacznikami Sphinx , ponieważ są one powszechnie używane i stają się de facto standardem do dokumentowania projektów w Pythonie, po części ze względu na doskonałą usługę readthedocs.org . Aby sparafrazować przykład z dokumentacji Sphinx jako urywek Python:

def send_message(sender, recipient, message_body, priority=1):
   '''
   Send a message to a recipient

   :param str sender: The person sending the message
   :param str recipient: The recipient of the message
   :param str message_body: The body of the message
   :param priority: The priority of the message, can be a number 1-5
   :type priority: integer or None
   :return: the message id
   :rtype: int
   :raises ValueError: if the message_body exceeds 160 characters
   :raises TypeError: if the message_body is not a basestring
   '''

Ten znacznik obsługuje odsyłacze między dokumentami i nie tylko. Zauważ, że dokumentacja Sphinx używa (np.), :py:attr:Podczas gdy możesz po prostu użyć :attr:podczas dokumentowania z kodu źródłowego.

Oczywiście istnieją inne narzędzia do dokumentowania interfejsów API. Jest bardziej klasyczny Doxygen, który używa \param poleceń, ale nie są one specjalnie zaprojektowane do dokumentowania kodu Pythona, tak jak Sphinx.

Zwróć uwagę, że jest tutaj podobne pytanie z podobną odpowiedzią ...

anarcat
źródło
9
Jest to styl używany domyślnie przez automatyczne generowanie komentarzy PyCharm
Josiah Yoder
A co ze składnią typów złożonych, takich jak listy rzeczy?
matanster
to jest list.
anarcat
33

Konwencje:

Przybory:


Aktualizacja: Od Pythona 3.5 możesz używać podpowiedzi typu, które są zwartą, czytelną maszynowo składnią:

from typing import Dict, Union

def foo(i: int, d: Dict[str, Union[str, int]]) -> int:
    """
    Explanation: this function takes two arguments: `i` and `d`.
    `i` is annotated simply as `int`. `d` is a dictionary with `str` keys
    and values that can be either `str` or `int`.

    The return type is `int`.

    """

Główną zaletą tej składni jest to, że jest definiowana przez język i jest jednoznaczna, dzięki czemu narzędzia takie jak PyCharm mogą z łatwością z niej skorzystać.

Jakub Roztocil
źródło
12
Chociaż ta odpowiedź jest obecnie najbardziej opiniotwórcza, żaden z powyższych PEP nie zawiera konwencji określania typów argumentów metody.
koriander
11

Ciągi dokumentacyjne Pythona są dowolne , możesz je dokumentować w dowolny sposób.

Przykłady:

def mymethod(self, foo, bars):
    """
    Does neat stuff!
    Parameters:
      foo - a foo of type FooType to bar with.
      bars - The list of bars
    """

Istnieją pewne konwencje, ale Python nie narzuca żadnej z nich. Niektóre projekty mają swoje własne konwencje. Niektóre narzędzia do pracy z dokumentami również są zgodne z określonymi konwencjami.

nosklo
źródło
3

Główny nurt jest, jak już wskazały inne odpowiedzi, prawdopodobnie idąc drogą Sfinksa , abyś mógł użyć Sfinksa do późniejszego wygenerowania tych wymyślnych dokumentów.

Biorąc to pod uwagę, osobiście od czasu do czasu używam stylu komentowania w tekście.

def complex(  # Form a complex number
        real=0.0,  # the real part (default 0.0)
        imag=0.0  # the imaginary part (default 0.0)
        ):  # Returns a complex number.
    """Form a complex number.

    I may still use the mainstream docstring notation,
    if I foresee a need to use some other tools
    to generate an HTML online doc later
    """
    if imag == 0.0 and real == 0.0:
        return complex_zero
    other_code()

Jeszcze jeden przykład, z kilkoma drobnymi szczegółami udokumentowanymi w tekście:

def foo(  # Note that how I use the parenthesis rather than backslash "\"
          # to natually break the function definition into multiple lines.
        a_very_long_parameter_name,
            # The "inline" text does not really have to be at same line,
            # when your parameter name is very long.
            # Besides, you can use this way to have multiple lines doc too.
            # The one extra level indentation here natually matches the
            # original Python indentation style.
            #
            # This parameter represents blah blah
            # blah blah
            # blah blah
        param_b,  # Some description about parameter B.
            # Some more description about parameter B.
            # As you probably noticed, the vertical alignment of pound sign
            # is less a concern IMHO, as long as your docs are intuitively
            # readable.
        last_param,  # As a side note, you can use an optional comma for
                     # your last parameter, as you can do in multi-line list
                     # or dict declaration.
        ):  # So this ending parenthesis occupying its own line provides a
            # perfect chance to use inline doc to document the return value,
            # despite of its unhappy face appearance. :)
    pass

Korzyści (jak @ mark-horvath wskazał już w innym komentarzu) to:

  • Co najważniejsze, parametry i ich doc zawsze pozostają razem, co przynosi następujące korzyści:
  • Mniej wpisywania (nie ma potrzeby powtarzania nazwy zmiennej)
  • Łatwiejsza konserwacja po zmianie / usunięciu zmiennej. Po zmianie nazwy jakiegoś parametru nigdy nie będzie jakiegoś osieroconego akapitu dokumentu dotyczącego parametrów.
  • i łatwiej znaleźć brakujący komentarz.

Niektórzy mogą pomyśleć, że ten styl wygląda „brzydko”. Ale powiedziałbym, że „brzydki” to subiektywne słowo. Bardziej neutralnym sposobem jest stwierdzenie, że ten styl nie jest głównym nurtem, więc może wyglądać mniej znajomo, a przez to mniej komfortowo. Ponownie „wygodne” jest również subiektywnym słowem. Chodzi o to, że wszystkie opisane powyżej korzyści są obiektywne. Nie możesz ich osiągnąć, jeśli podążasz standardową drogą.

Miejmy nadzieję, że któregoś dnia w przyszłości pojawi się narzędzie do generowania dokumentów, które również będzie obsługiwać taki styl wbudowany. To będzie napędzać adopcję.

PS: Ta odpowiedź wynika z moich własnych preferencji dotyczących używania komentarzy w tekście, kiedy tylko uznam to za stosowne. Używam tego samego stylu wbudowanego do dokumentowania słownika .

RayLuo
źródło
1

Opierając się na odpowiedzi na wskazówki dotyczące typu ( https://stackoverflow.com/a/9195565/2418922 ), która zapewnia lepszy uporządkowany sposób dokumentowania typów parametrów, istnieje również ustrukturyzowany sposób dokumentowania zarówno typu, jak i opisów parametrów:

def copy_net(
    infile: (str, 'The name of the file to send'),
    host: (str, 'The host to send the file to'),
    port: (int, 'The port to connect to')):

    pass

przykład zaczerpnięty z: https://pypi.org/project/autocommand/

DreamFlasher
źródło
1
Czy to jest oficjalna składnia? Jest bardzo przydatny, ale nie mogę go znaleźć w oficjalnych dokumentach / PEP ...
Ofri Raviv
1
Też chciałbym wiedzieć, jeśli jest do tego PEP.
DreamFlasher,
-1

Dokumenty są przydatne tylko w środowiskach interaktywnych, np. Powłoce Pythona. Podczas dokumentowania obiektów, które nie będą używane interaktywnie (np. Obiekty wewnętrzne, wywołania zwrotne frameworka), równie dobrze możesz używać zwykłych komentarzy. Oto styl, którego używam do zawieszania komentarzy z wcięciem przy elementach, każdy w osobnym wierszu, więc wiesz, że komentarz dotyczy:

def Recomputate \
  (
    TheRotaryGyrator,
      # the rotary gyrator to operate on
    Computrons,
      # the computrons to perform the recomputation with
    Forthwith,
      # whether to recomputate forthwith or at one's leisure
  ) :
  # recomputates the specified rotary gyrator with
  # the desired computrons.
  ...
#end Recomputate

Nie możesz tego zrobić z dokumentami.

Lawrence D'Oliveiro
źródło
46
Och, ten wygląda brzydko.
Misha Akovantsev
1
Brzydkie tak? Ciekawy pomysł ... też tak.
David
2
Komentarze wbudowane do zmiennych są bardzo rozsądne, mniej wpisywania (nie ma potrzeby powtarzania nazwy zmiennej), łatwiejsza konserwacja przy zmianie / usuwaniu zmiennej ... łatwiej jest znaleźć brakujący komentarz. Połączyłby to z odpowiednim napisem pod podpisem. +1
Mark Horvath
To nie działa jako dokumentacja. Jeśli skomentujesz swój pakiet w ten sposób, a użytkownik PyCharm go pobierze, nie będzie mógł sprawdzić, co robi każdy parametr bez dostępu do dokumentacji - czego nie będziesz w stanie wygenerować za pomocą żadnego oprogramowania. Chyba że stworzysz własne. Dlatego OP prosi o określenie tego w dokumentacji. Przepraszam tak późno.
To jest po prostu okropne.
Michael Walters