Seite 1 von 2

Ab wann ergeben Klassen Sinn?

Verfasst: Samstag 7. Dezember 2013, 12:12
von Hellstorm
Hallo zusammen,

ich bin gerade irgendwie stark begeistert von Klassen und möchte jetzt am liebsten für alles eine Klasse erstellen :D

Als Beispiel hätte ich hier z.b. mehrere Dateien, von denen ich die den Dateinamen, den Pfad und die Dateigröße brauche. Würde es da Sinn ergeben, schon direkt eine Klasse zu erstellen, der ich dann einfach nur anfangs den kompletten Dateipfad übergebe und die dann von selber den Dateinamen (ohne Pfad) und die Dateigröße herausfindet? Dann könnte ich später ja einfach die Dateigröße auslesen, ohne das bei jedem Aufruf selber zu machen. Die Objekte würde ich dann bequem in einer Liste speichern.

Ich frage mich nur, ob das überhaupt Sinn macht? Oder ist das schon Overkill und ich sollte lieber mit einfachen Strings arbeiten und je nach Bedarf die Dateigröße herausfinden? Insbesondere da die Klasse ja selber nicht wirklich viel macht, sondern einfach nur die Daten sammeln würde.

Danke! :)

Re: Ab wann ergeben Klassen Sinn?

Verfasst: Samstag 7. Dezember 2013, 16:05
von diesch
Das kommt auf dein Programm an.

Wenn du Name und Größe an meheren Stellen in deinem Programm brauchst, kann eine Klasse sinnvoll sein. Wenn du die nur einmal benötigst, ist eine eigene Klasse vermutlich übertrieben.

Re: Ab wann ergeben Klassen Sinn?

Verfasst: Samstag 7. Dezember 2013, 16:14
von Hellstorm
Ja, doch, brauchte ich jetzt schon an mehreren Stellen. Aber ist eine Klasse denn irgendwie vom Speicherbedarf zu groß, oder wieso ist sie teilweise übertrieben? Oder hat sie z.B. großen Einfluss auf die Geschwindigkeit?

Insbesondere für solche einfachen Sammlungen von Attributen frage ich mich das. Ich habe mal in einem C++-Kurs struct als Möglichkeit zur Strukturierung von verschiedenen Attributen gelernt, wobei struct ja auch einfach eine Klasse ist. Da frage ich mich jetzt natürlich, ob sich das lohnt oder nicht. Zumindest von der Übersicht her scheint es mir etwas einfacher, wenn ich nachher einfach datei.name und datei.groesse schreiben kann.

Re: Ab wann ergeben Klassen Sinn?

Verfasst: Samstag 7. Dezember 2013, 16:24
von snafu
@Hellstorm: Wenn du nur einen Datencontainer mit benannten Attributen benötigst, dann ist namedtuple() vermutlich eher das, was du suchst...

Im Übrigen haben Klassen auch bei einmaliger Verwendung ihre Berechtigung. Ich wüsste nicht, warum man das nur davon abhängig machen sollte.

Re: Ab wann ergeben Klassen Sinn?

Verfasst: Samstag 7. Dezember 2013, 16:38
von Hellstorm
snafu hat geschrieben:@Hellstorm: Wenn du nur einen Datencontainer mit benannten Attributen benötigst, dann ist namedtuple() vermutlich eher das, was du suchst...
Naja, gut, ging mir auch darum, dass die Klasse praktisch selber einige Aktionen macht: Dateigröße herausfinden, Dateinamen aus dem Dateipfad abtrennen usw. namedtuple() werde ich mir aber mal anschauen, danke!

Re: Ab wann ergeben Klassen Sinn?

Verfasst: Samstag 7. Dezember 2013, 16:40
von BlackJack
@Hellstorm: Ob sich das lohnt kannst Du letztendlich nur anhand des konkreten Einsatzes festmachen. Das ist in diesem Fall eine Abwägung zwischen lesbarkeit und Aufwand, sowohl was die Programmierung betrifft als auch Speicherbedarf und Laufzeit.

Bevor Du das Rad selber erfindest, könntest Du auch einen Blick auf vorhandene Module wie das `Unipath`-Paket werfen:

Code: Alles auswählen

In [25]: p = unipath.Path('tmp/otrs.sql')

In [26]: print p.name
otrs.sql

In [27]: p.size()
Out[27]: 141843290L

Re: Ab wann ergeben Klassen Sinn?

Verfasst: Samstag 7. Dezember 2013, 18:03
von bwbg
Ich stelle mir immer die Frage, ob ich etwas repräsentieren möchte, das einen inneren Zustand besitzt (es "ist etwas"). Ist dies nicht der Fall ist dies meist ein klares Zeichen für eine Funktion.

OOP ist keine Religion und kein Allheilmittel. Sie ist lediglich Werkzeug.

Re: Ab wann ergeben Klassen Sinn?

Verfasst: Sonntag 8. Dezember 2013, 03:35
von snafu
Ich sehe das ein bißchen weiter gefasster: Für mich können Klassen manchmal auch Dinge gruppieren, die zu "gering" für ein eigenes Modul wären. Eine Klasse ist für mich in diesen Fällen eher so etwas wie eine Aufgabe, deren Arbeitsschritte durch Methoden repräsentiert werden. Ich denke einfach, man kann Klassen in sehr verschiedenen Zusammenhängen gebrauchen.

Re: Ab wann ergeben Klassen Sinn?

Verfasst: Sonntag 8. Dezember 2013, 04:32
von BlackJack
@snafu: s/gebrauchen/missbrauchen/ :twisted:

Re: Ab wann ergeben Klassen Sinn?

Verfasst: Sonntag 8. Dezember 2013, 05:08
von diesch
Der Speicherbedarf ist wohl nur relevant, wenn du mit viele Millionen Dateien arbeitest - auf ein paar MByte mehr oder weniger kommt es da heutzutage typischerweise nicht an.

Bei der Laufzeit ist eigentlich nur die Konstruktion der Instanzen teuer, der Zugriff auf Objekt-Attribute ist nicht aufwändiger als der auf normale Variablen.

Wichtiger ist in den allermeisten Fällen, dass der Code möglichst fehlerfrei und für dich (und ggf. alle anderen Beteiligten) gut verständlich und wartbar ist.

Re: Ab wann ergeben Klassen Sinn?

Verfasst: Sonntag 8. Dezember 2013, 09:13
von Hellstorm
Naja, so wie ich das sehe, könnte ich entweder eine Funktion schreiben, die die entsprechenden Daten erstellt und dann ein Dictionary zurückgibt. Oder ich schreibe eine Klasse, die die entsprechenden Daten erstellt und dann als Klassenattribute speichert. Insbesondere da ich von der Klasse eh nur vielleicht maximal 2-3 Objekte brauche, scheint mir das dann relativ egal zu sein.

Ich glaube ich werde dann doch bei der Klasse bleiben. Ist für mich zum gegebenen Stand etwas übersichtlicher (insbesondere da ich nicht mit ["..."] hantieren muss, sondern nur mit . (Also objekt.name anstatt objekt["name"]). Das scheint mir den Quelltext etwas lesbarer zu machen) und eventuell kann ich das nachher noch etwas besser erweitern. Ich werde die anderen Lösungen aber im Kopf behalten.

Im Moment ist die Klasse übrigens derartig banal:

Code: Alles auswählen

class File(object):
    def __init__(self, path):
        self.name = os.path.split(path)[1]
        self.path = path
        self.size = os.path.getsize(path)
        
    def __str__(self):
        return self.name
Danke für alle Antworten :)

Re: Ab wann ergeben Klassen Sinn?

Verfasst: Sonntag 8. Dezember 2013, 10:23
von snafu
Anstatt ``os.path.split(p)[1]`` könntest du übrigens auch ``os.path.basename(p)`` verwenden. ;)

Re: Ab wann ergeben Klassen Sinn?

Verfasst: Sonntag 8. Dezember 2013, 10:40
von Hellstorm
Danke :)

Re: Ab wann ergeben Klassen Sinn?

Verfasst: Sonntag 8. Dezember 2013, 11:33
von cofi
Damit hast du ein Konsistenzproblem, wenn jemand `path` (oder generell alle Attribute ..) aendert. Darum wuerde ich `name` und `size` als property implementieren.
Alternativ wuerde ich `namedtuple` benutzen und statt einer Klasse `File` eine Factory Funktion erstellen, die dann so ein `namedtuple` zurueckgibt.

Kleines Problem und schon so viele Alternativen :)

Re: Ab wann ergeben Klassen Sinn?

Verfasst: Sonntag 8. Dezember 2013, 12:00
von BlackJack
Ich würde auch ein `namedtuple` verwenden. Solange die Klasse nur als „Aufbewahrungsort” für Datenattribute dient, noch dazu wenn es von Vorteil wäre die nicht mehr ändern zu können, ist das IMHO eine gute Datenstruktur. Das ist in Python sozusagen das Äquivalent zu einem `struct` in C — mit der zusätzlichen Einschränkung dass den Attributen nachträglich nichts mehr zugewiesen werden kann.

Aber falls das untergegangen sein sollte: Es gibt das `unipath`-Paket. Muss man zwar erst installieren, aber das bietet Pfade/Dateien schon als eine objektorientierte API über `os`, `os.path`, und `shutil`.

Re: Ab wann ergeben Klassen Sinn?

Verfasst: Sonntag 8. Dezember 2013, 12:13
von Hellstorm
BlackJack hat geschrieben:Ich würde auch ein `namedtuple` verwenden. Solange die Klasse nur als „Aufbewahrungsort” für Datenattribute dient, noch dazu wenn es von Vorteil wäre die nicht mehr ändern zu können, ist das IMHO eine gute Datenstruktur. Das ist in Python sozusagen das Äquivalent zu einem `struct` in C — mit der zusätzlichen Einschränkung dass den Attributen nachträglich nichts mehr zugewiesen werden kann.
OK, dann werd ich das wohl verwenden.
BlackJack hat geschrieben: Aber falls das untergegangen sein sollte: Es gibt das `unipath`-Paket. Muss man zwar erst installieren, aber das bietet Pfade/Dateien schon als eine objektorientierte API über `os`, `os.path`, und `shutil`.
Ne, das habe ich schon gelesen, danke :D Aber mir schien es etwas sinnlos für zwei oder drei Aktionen mit einer Datei direkt eine zusätzliche Bibliothek zu installieren, gerade wenn das auch wunderbar mit den eingebauen Python-Werkzeugen klappt.
Wenn man mehr mit Dateien macht ist das sicherlich nützlich, aber bei mir lohnte sich das einfach nicht.

Re: Ab wann ergeben Klassen Sinn?

Verfasst: Sonntag 8. Dezember 2013, 12:28
von Hellstorm
Ok, habe es jetzt folgendermaßen mit namedtuple gemacht:

Code: Alles auswählen

import collections
import os

File = collections.namedtuple("File", ["path", "name", "size"])

def create_filetuple(path):
    name = os.path.basename(path)
    size = os.path.getsize(path)
    file = File(path, name, size)
    
    return file

Ist das so gut, oder irgendwie anders? Das einzige, was ich mir da jetzt noch wünschen würde, wäre, wenn man das wie ein dictionary auch als test["name"] verwenden kann, aber leider muss man dafür Zahlen verwenden.

Re: Ab wann ergeben Klassen Sinn?

Verfasst: Sonntag 8. Dezember 2013, 12:44
von bwbg
Verwende doch einfach test.name.

Re: Ab wann ergeben Klassen Sinn?

Verfasst: Sonntag 8. Dezember 2013, 12:50
von BlackJack
@Hellstorm: Man könnte die Funktion deutlich knapper formulieren und zwar IMHO ohne das sie dadurch schwerer zu verstehen ist. Damit könnte man dann auch ganz einfach vermeiden den Namen `file` (lokal) an etwas anderes als den `file`-Typ zu binden.

Der Suffix `tuple` in dem Funktionsnamen ist keine gute Idee denn man kann falls man doch noch Funktionalität zu den Daten packen möchte das `namedtuple` problemlos durch eine Klasse ersetzen. Damit würde man den Funktionsnamen dann auch ändern müssen.

Code: Alles auswählen

def create_file(path):
    return File(path, os.path.basename(path), os.path.getsize(path))
Wozu brauchst Du Zugriff über Schlüssel? Statt ``test['name']`` kannst Du doch ``test.name`` schreiben‽ Falls das Attribut variabel sein soll, muss man halt wie üblich bei Attributzugriffen die `getattr()`-Funtkion verwenden. Eventuell kann je nach Anwendungszweck auch `operator.attrgetter()` und vielleicht auch `functools.partial()` nützlich sein.

Re: Ab wann ergeben Klassen Sinn?

Verfasst: Sonntag 8. Dezember 2013, 13:18
von snafu
Man könnte sogar einen eigenen Konstruktor schreiben:

Code: Alles auswählen

import collections
import os

class File(collections.namedtuple('File', 'path, name, size')):
    def __new__(cls, path):
        return super(File, cls).__new__(
            cls, path, os.path.basename(path), os.path.getsize(path)
        )
Hier ist es dementsprechend die `File`-Klasse, die den Dateipfad entgegennimmt und daraus ein passendes `namedtuple` erzeugt.