Seite 1 von 1

Modul programmieren

Verfasst: Sonntag 14. Dezember 2014, 16:41
von pixewakb
Hi,

ich programmiere gerade ein Modul, das mir verschiedene Tools bereitstellt. Dabei ergeben sich für mich einige Fragen, wie die optimale Lösung aussehen könnte:

(1) Besser separate Funktionen oder besser statische Methoden als Teil einer Klasse?

Ich kann beides, aktuell habe ich da nur Funktionen reingepackt, so dass ich im Kern etwa folgendes mache:

Code: Alles auswählen

from modul import function
Macht es Sinn oder würde man produktiv besser auf statische Methoden wechseln? Irgendeine Erfahrung, gibt es eine Standardlösung für die Frage oder wird es später Vor- oder Nachteile je nach Lösung geben?

(2) Ich nutze die Funktionen für meine Aufgaben und habe erst einmal nicht an eine Weitergabe gedacht; u. a. berechne ich den Durchschnitt und zwar auf x Elemente einer Liste.

Im Kern mache ich so etwas:

Code: Alles auswählen


def get_durchschnitt(werteliste):
    return sum(werteliste) / len(werteliste)

werteliste = []
print(get_durchschnitt(werteliste[-20:]))

print(get_durchschnitt(werteliste[-30:]))

Ich könnte ja im Prinzip stattdessen auch wie folgt herangehen:

Code: Alles auswählen


def get_durchschnitt(werteliste, n):
    return sum(werteliste[-n:]) / n

werteliste = []
print(get_durchschnitt(werteliste, 20))

print(get_durchschnitt(werteliste, 30))

Gibt es bei den beiden Varianten Vor- oder Nachteile oder würdet ihr eine Lösung bevorzugen? Die zweite Lösung ist expliziter als die erste Herangehensweise, nur frage ich mich gerade, ob es Sinn macht einer Funktion immer die komplette Werteliste (mit > 5.000 Werten) zu übergeben. Irgendwelche Empfehlungen???

Re: Modul programmieren

Verfasst: Sonntag 14. Dezember 2014, 16:52
von BlackJack
@pixewakb: Ad (1): Ganz klar Funktionen. Welchen Vorteil versprichst Du Dir denn von statischen Methoden? Das ist doch hauptsächlich ein Workaround bei Sprachen wie Java um doch so etwas wie Funktionen haben zu können. In Python sind die für den eher seltenen Fall das man eine polymorphe Funktion innerhalb einer (echten) Methode braucht die vom Datentyp abhängt auf dem die Methode aufgerufen wurde.

Ad (2): Da würde ich die erste Variante nehmen weil die zweite ewas macht was mehr ist als den Durchschnitt zu berechnen und da wohl alleine vom Namen niemand drauf kommen würde. Und jeder der den Durchschnitt von allen Elementen berechnen möchte und die Zusatzfunktionalität nicht benötigt muss immer auch ein zweites Argument übergeben. Selbst wenn man das mit einem Default-Wert löst wird dann innerhalb der Funktion immer eine Kopie der Liste angelegt, auch wenn man gar keinen Ausschnitt sondern alles berechnen möchte. Und die Funktion geht dann auch nur mit Objekten die „slicing” überhaupt verstehen.

Re: Modul programmieren

Verfasst: Sonntag 14. Dezember 2014, 17:21
von pixewakb
Bei der 2. Version mit zusätzlichem Parameter ist es expliziter, das hätte dafür gesprochen. Statische Methoden sind bei Weigend erklärt und zwar um "Toolboxen" zu programmieren, darum hätte ich es eingesetzt, nach der Einführung lerne/arbeite ich.

Danke fürs Feedback! Das Modul wird später mal etliche Funktionen bereithalten und da habe ich gerade bei 5 Funktionen schon Sorge, dass ich grundlegend im Design etwas falsch mache.

Re: Modul programmieren

Verfasst: Sonntag 14. Dezember 2014, 19:37
von EyDu
pixewakb hat geschrieben:Bei der 2. Version mit zusätzlichem Parameter ist es expliziter, das hätte dafür gesprochen.
Nee, zwei Parameter sind mehr und unnötige Schreibarbeit und dazu noch fehleranfällig. Ein Objekt sollte schon selber wissen, wie viele Elemente es enthält. Und wenn es das nicht weiß, dann kann das spätestens dann entschieden werden, wenn über die Elemente iteriert wird.

Ich vermute mal, dass du das "explizit" einfach überinterpretiert hast. Explizit bedeutet nicht, dass du unnötig offensichtliche Dinge hinschreiben sollst. Wenn du das machst, dann wird der Code so unübersichtlich, dass er kaum noch lesbar ist. Hinzu kommt dann noch, dass die wirklich wichtigen Dinge dann leicht übersehen werden.

Re: Modul programmieren

Verfasst: Sonntag 14. Dezember 2014, 20:08
von pixewakb
Im konkreten Fall brauche ich eine Funktion, die Durchschnitte für eine Messwertliste erstellt, wobei mich die Messwerte pro Woche (n = 7), für 2 Wochen (n = 14) und dann im Monat, Quartal usw. interessieren. Gedanklich habe ich Sorge, dass ich irgendwann falsche Messwerte übergebe und dann nicht merke, dass die Rechnung falsch wird, weil z. B. die Messwertliste gar keine 7 Daten enthält. Das ist mein sehr konkretes Problem.

Re: Modul programmieren

Verfasst: Sonntag 14. Dezember 2014, 20:27
von BlackJack
@pixewakb: Und wo ist da der Unterschied zwischen den beiden Varianten? Den Fehler kannst Du in beiden Fällen problemlos machen.

Re: Modul programmieren

Verfasst: Sonntag 14. Dezember 2014, 20:48
von pixewakb
Ich habe z. B. eine Funktion, wo ich für jeden Messwert einer Reihe die drei aufeinanderfolgenden vergleiche und verarbeite. Wenn ich das auch für den ersten machen will, dann muss ich folglich statt werte[-14:] dann werte[-16:] übergeben. Persönlich habe ich "Sorge", dass ich irgendwann nicht mehr bewusst habe, welche Daten die jeweilige Funktion erfordert und sich so Rechenfehler einschleichen. (Im Kern kann ich mein Magengrummeln also noch nicht genau fassen, zumindest nicht sprachlich formulieren.)

Re: Modul programmieren

Verfasst: Sonntag 14. Dezember 2014, 20:57
von BlackJack
@pixewakb: Die Sorge verstehe ich, aber nicht wo der Unterschied bei den Varianten ist. Ob Du nun daran denken musst statt ``f(v[-14:])`` dann ``f(v[-16:])`` zu schreiben oder statt ``f(v, 14)`` dann ``f(v, 16)`` ist doch letztendlich egal, man muss dran denken und man kann in beiden Fällen den gleichen Fehler machen.

Re: Modul programmieren

Verfasst: Dienstag 16. Dezember 2014, 21:24
von pixewakb
Noch eine Frage:

Sagen wir mal ich brauche eine Funktion der Art berechne_xyz(...), wie würde diese Funktion dann typischerweise heißen?

Im Tutorial gibt es u. a. fib() für Fibonacci-Zahlen; von Klassen kenne ich nur die get-Funktionen. Gibt es einen Standardnamen, der anzeigt, dass ein Skript einen Wert xyz berechnet? Würde man XYZ dann übrigens groß oder klein schreiben???

Bin bei PEP8 nicht fündig (in den Abschnitten) geworden und konnte auf die Schnelle nichts finden.

Wenn ich das richtig deute, wird auf ein vorangestelltes get, calculate o. ä. ganz verzichtet!?

https://docs.python.org/2/library/math.html

Gibt es davon abweichende Namen? Konventionen?

Re: Modul programmieren

Verfasst: Dienstag 16. Dezember 2014, 21:44
von BlackJack
@pixewakb: Die Gross-/Kleinschreibung von Funktionen sollte in PEP8 eigentlich abgedeckt sein: `klein_mit_unterstrichen()`.

Ansonsten beschreiben Funktionsnamen üblicherweise Tätigkeiten. `get_*()` deutet auf ”Getter” hin bei denen man üblicherweise erwartet das da nichts komplizierteres passiert sondern ein irgendwo hinterlegter Wert geholt wird. `calculate_*()` wäre für Berechnungen schon ganz gut — falls einem nichts passenderes einfällt. Wenn es mathematische Sachen sind, wird oft auch der Name der Funktion verwendet der in der Literatur üblich ist. So ganz eindeutig kann man da nichts sagen.

Die Namensgebung im `math`-Modul ist nicht frei gewählt, das sind im Grunde die Namen der C-Funktionen aus der C-Standardbibliothek.

Re: Modul programmieren

Verfasst: Dienstag 16. Dezember 2014, 21:44
von MagBen
pixewakb hat geschrieben:Sagen wir mal ich brauche eine Funktion der Art berechne_xyz(...), wie würde diese Funktion dann typischerweise heißen?
Schau Dir einfach mal an, wie es in anderen Bibliotheken gemacht wird, dann bekommst Du schon Ideen für eigene Namen: http://docs.scipy.org/doc/numpy/referen ... stics.html

Statistische Grundfunktionen wie mean, std, median, ... braucht man übrigens nicht selbst zu implementieren, es ist alles schon da. Wenn Dir die paar statistischen Grundfunktionen in Numpy nicht ausreichen, dann schau Dir mal Pandas an: http://pandas.pydata.org/. Unglaublich was da an mächtiger Funktionalität geboten wird, insbesondere in Verbindung mit ipython notebook.