API Script doc: mit "@return" mehrere Ergebnisse zurückgeben

Wenn du dir nicht sicher bist, in welchem der anderen Foren du die Frage stellen sollst, dann bist du hier im Forum für allgemeine Fragen sicher richtig.
Antworten
python_bunny
User
Beiträge: 16
Registriert: Dienstag 19. April 2011, 12:46

Hallo Forum,

beim schreiben meiner API bin ich auf folgendes Problem gestoßen:
Ich kann in meiner Funktion immer nur einen "return" Datentyp und Wert dokumentieren. Ich habe aber eine Funktion, die mehrere "return" Werte zurückgibt. Hier der Code für die "return" Werte:

Code: Alles auswählen

return value1, value2
Nun versuche ich das so zu dokumentieren:

Code: Alles auswählen

    @returntype: C{int}
    @return: Documentation of value1.  

    @returntype: C{int}
    @return: Documentation of value2.    
Leider beschwert sich ePyDoc beim Erstellen der API mit folgender Fehlermeldung:
"Warning: Redefinition of return value type
Warning: Redefinition of return value description"

Das Ergebnis in der API ist, dass der erste Rückgabewert nicht existiert, sondern nur der zweite. Der erste Rückgabewert wird also tatsächlich von dem zweiten überschrieben, so wie es in der Fehlermeldung angezeigt wird.

Ich habe bei meiner Suche im Netz nur API Beispiele mit einem Rückgabewert pro Funktion gefunden. Welche Möglichkeit kennt Ihr, beide "return" values zu dokumentieren?

Danke

Gruß
python_bunny
JonasR
User
Beiträge: 251
Registriert: Mittwoch 12. Mai 2010, 13:59

Hey python_bunny,

Das ganze mit dem "@" kommt mir ein wenig spanisch vor :D Ich kenne lediglich diese Kommentar Schreibweisen:

Code: Alles auswählen

# Text
## Text
'''
    Text
    Mehrzeilig
'''
Ansonsten definierst du die Rückgabe schon richtig.

Code: Alles auswählen

>>> def foobar():
...     return 1, 2, 3
...
>>> array = foobar()
>>> print array
(1, 2, 3)
>>># Oder
>>> first, second, third = foobar()
>>> print first
1
>>> print third
3
Benutzeravatar
b.esser-wisser
User
Beiträge: 272
Registriert: Freitag 20. Februar 2009, 14:21
Wohnort: Bundeshauptstadt B.

Dein Return-type ist 'tuple()'. Und dieses tuple wird von Python automatisch ausgepackt:

Code: Alles auswählen

In [1]: def foo():
   ...:     return 42, 17+4
   ...:

In [2]: a = foo()

In [3]: repr(a)
Out[3]: '(42, 21)'

In [4]: type(a)
Out[4]: <type 'tuple'>

In [5]: b, c = foo()

In [6]: b
Out[6]: 42

In [7]: c
Out[7]: 21
Also kannst du das auch als ein return dokumentieren.

hth, Jörg
Wir haben schon 10% vom 21. Jahrhundert hinter uns!
python_bunny
User
Beiträge: 16
Registriert: Dienstag 19. April 2011, 12:46

Hallo JonasR,

natürlich kann man die Raute "#" verwenden, um Quellcode zu dokumentieren. Wenn man aber eine API (= Application programming interface) erstellen will zu seinem Programm, dann muss man eine Skriptsprache benutzten. Das Programm, welches die API Doku erstellt, arbeitet dann Schritt für Schritt die Einträge entsprechend dieser Skriptsprache ab. Die Skriptsprache heißt bei uns konkret Python Script Doc. Und das Programm mit dem man die API Dokumentation erstellt heißt "ePyDoc". Das "@" Zeichen ist ein Bestandteil dieser Skriptsprache und daher verwende ich es, damit es von ePyDoc überhaupt erkannt wird.

Gruß
python_bunny
JonasR
User
Beiträge: 251
Registriert: Mittwoch 12. Mai 2010, 13:59

@python-bunny
klingt ja recht interessant :D Ich werde mir das mal anschauen ;)
python_bunny
User
Beiträge: 16
Registriert: Dienstag 19. April 2011, 12:46

@ b.esser-wisser:
Du hast Recht, wenn zwei Werte ausgegeben werden, dann ist das aus programmiertechnischer Sicht ein Tupel (ich weiß es nicht besser, ich glaube Dir das jetzt einfach mal). In der API Dokumentation ist es dennoch hilfreich, jeden Ausgabewert einzeln darzustellen. Schließlich ist der Vorteil der API die Übersichtlichkeit und einfache Darstellung.

Für alle, die sich sonst noch für dieses Thema interessieren, habe ich hier einen Lösungsvorschlag gefunden:

Code: Alles auswählen

    @return: 
      - B{value1} (int) - Documentation for value1.  
      - B{value2} (int) - Documentation for value2.  

Die "return" Werte einer Funktion werden dann in der API genauso differenziert dargestellt wie ihre Eingangsparameter. Das ist die beste Lösung, die mir bisher einfällt. Wenn jemand etwas Eleganteres hat, würde ich mich freuen, das zu sehen.

Danke

Grüße
python_bunny
Xynon1
User
Beiträge: 1267
Registriert: Mittwoch 15. September 2010, 14:22

@python_bunny
Man könnte auch einfach das "tuple" angeben. zB so:

Code: Alles auswählen

"""
@rtype: C{tuple(int, int)}
@return: X- und Y-Koordinaten.
Wenn man ein tuple zurückgibt von dem man die Länge nicht kennt, hat das eigentlich immer nur einen Datentyp und kann also so angegeben werden: "tuple(int)", bei mehreren, wie "tuple(int, str)" kann man davon ausgehen das nur zwei Werte enthalten sind.

Das geht solange die Werte eine gleiche bzw. ähnliche Bedutung haben. Sollten sie sich aber grob unterscheiden und koplexe Bedeutungen haben. Beispielsweise Name, Alter, Geb.-Datum, dann würde ich etwas in der Art schreiben:

Code: Alles auswählen

"""
@rtype: C{tuple(str, int, datetime)} 
@return: - Name: Den Name von einer Person.
         - Alter: Das Alter einer Person, von dem Zeitpunkt an wo sie geboren wurde.
         - Datum: Das Geburtsdatum der Person.
Beispiel ist leicht übertrieben :mrgreen:. Es sollte für den Leser sofort verständlich sein was die Funktion liefert. Sowas lohnt sich also nur wenn du wirklich einige komplexere Konstruckte wie ein Wörterbuch oder etwas in der Art übergibst, bei solchen Einzelsachen, kann man das auch noch in ein, zwei Sätzen formulieren.
Traue keinem Computer, den du nicht aus dem Fenster werfen kannst.
Xynon auf GitHub
python_bunny
User
Beiträge: 16
Registriert: Dienstag 19. April 2011, 12:46

@ Xynon1: Ja, das macht schon Sinn, was Du schreibst. So werde ich das auch machen.

Danke

Gruß

python_bunny
Darii
User
Beiträge: 1177
Registriert: Donnerstag 29. November 2007, 17:02

python_bunny hat geschrieben:Die Skriptsprache heißt bei uns konkret Python Script Doc.
Das ist keine Scriptsprache, sondern allenfalls eine Auszeichnungssprache.
Und das Programm mit dem man die API Dokumentation erstellt heißt "ePyDoc".
Benutzt zum Glück fast niemand, denn die von ePyDoc erstellten Dokus sind eine Zumutung.
BlackJack

@Darii: Wieso benutzt das fast niemand? Ich hatte den Eindruck, dass es *das* Dokumentationswerkzeug für Python ist um JavaDoc-ähnliche Dokumentation zu erzeugen. Alle Alternativen die ich bis jetzt gesehen habe, sind eher Eintagsfliegen gewesen oder werden nur von wenigen Projekten verwendet.

In letzter Zeit scheint sich Sphinx zum schreiben von Dokumentation zu verbreiten. Das ist dafür IMHO auch besser und schöner als generierte API-Dokumentation, aber dazu muss man die Dokumentation auch wirklich *schreiben*. Wenn man ein grösseres Programm "geerbt" hat, über das man sich dokumentierend einen Überblick verschaffen will oder muss, dann würde ich aber auch zu Epydoc greifen. Das ist dazu IMHO geeigneter als die `autodoc`-Erweiterung von Sphinx.

Ich würde in den Docstrings allerdings reStructuredText statt die Epydoc-Auszeichnung verwenden. Die kann Epydoc auch verarbeiten und sie ist wesentlich verbreiteter. Man könnte damit dann zum Beispiel auch irgend wann einmal wenn man sich eingearbeitet hat auf Sphinx umsteigen.
Xynon1
User
Beiträge: 1267
Registriert: Mittwoch 15. September 2010, 14:22

@Darii
Ich finde epydoc auch recht praktisch um schnelle einfache und dennoch verständliche und überschaubare API-Dokumentationen anzufertigen. Zumal man in der Doku immer auch mal schnell zum Quelltext schalten kann und auch gute Grafikbäume von den Modulen bzw. Paketen enthält, was die Orientierung bei fremden Quellcode sehr komfortable gestaltet. Das einzige was ich mir wünschen würde wäre eine Suchfunktion.

@BlackJack
Die "Epydoc-Auszeichnung"en nennen sich "epytext". Den ich dem "reStructuredText" vorziehe, weil es mir einfach besser gefällt(Also rein optisch). Natürlich hast du aber Recht reStructuredText ist weiter verbreitet und ist auch besser dokumentiert, ist allerdings nicht direkt auf epydoc zugeschnitten.
Traue keinem Computer, den du nicht aus dem Fenster werfen kannst.
Xynon auf GitHub
BlackJack

@Xynon1: Das mit dem optisch ist natürlich Geschmackssache, mir gefällt die "unaufdringlichere" Art von reStructuredText besser. Man kann da mit weniger "Tags" auskommen.

Natürlich ist reStructuredText nicht direkt auf Epydoc zugeschnitten, aber das wäre doch nur ein Problem, wenn man damit nicht alles Wichtige ausdrücken könnte was man mit epytext kann, oder wenn es deutlich umständlicher wäre das zu tun. Für die Formatierungen im Text hat reST eigene und IMHO einfache Syntax und für die @-tags kann man ja grundsätzlich erst einmal ``:tag: value`` anstelle von ``@tag value`` schreiben.
lunar

Sind diese Tags denn überhaupt nötig? Ich bin bisher immer ohne ausgekommen, und habe Docstrings immer nur im Fließtext geschrieben.
BlackJack

@lunar: Definiere "nötig". Wenn die Informationen in der Epydoc-Ausgabe an der richtigen Stelle stehen sollen, dann muss man sie schon entsprechend auszeichnen damit sie erkannt werden. Wenn man den Rückgabetyp nicht entsprechend auszeichnet, wird er in der Übersicht nicht in der Spalte vor der Funktion aufgeführt, Todo- und Bug-Einträge werden nicht auf den entsprechenden Seiten noch einmal gesammelt, Attribute erscheinen sonst nicht im Index und so weiter. Aber genau wegen solcher Sachen benutzt man Epydoc ja.
lunar

@BlackJack: Ich habe epydoc nie wirklich genutzt, daher auch meine Frage. In Sphinx sind diese Tags nichts besonderes ...
Antworten