Klasse oder Dict, was am besten nehmen?

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
friedduck
User
Beiträge: 76
Registriert: Montag 23. Juli 2012, 20:41

Hallo,

ich möchte in einem Projekt einen "wertespeicher" haben, der in mehreren Packages verfügbar sein soll.
Was soll ich am besten verwenden? Eine vorinitialisierte Klasse oder ein Dict verpackt in ein Modul?

Code: Alles auswählen

class Testklase(object):
  def __init__(self):
    self.wert1 = 'wert1'
    self.wert2 = 'wert2'

Code: Alles auswählen

def wertespeicher():
  meinwert = {'wert1':'wert1', 'wert2':'wert2'}
  return meinwert
und dann...

Code: Alles auswählen

from bla import Testklasse oder from bla import wertespeicher
BlackJack

@friedduck: Das kommt darauf an was Du am Ende damit vorhast. Falls das ein „globaler Wertespeicher” sein soll, dann würde ich zumindest hinterfragen ob das so gewollt/nötig ist.
friedduck
User
Beiträge: 76
Registriert: Montag 23. Juli 2012, 20:41

Hi Blackjack, du hast recht. es soll ein globaler Wertespeicher werden. Hast Du einen besseren Vorschlag für die Umsetzung? Die Werte kommen aus einer Datenbank.
BlackJack

@friedduck: Muss das denn wirklich global sein? Kann man die Daten nicht herum reichen? Oder jeweils von der DB abfragen? Was sind das für Daten?
Benutzeravatar
kbr
User
Beiträge: 1487
Registriert: Mittwoch 15. Oktober 2008, 09:27

friedduck hat geschrieben:es soll ein globaler Wertespeicher werden
Erstelle eine Klasse und reiche Instanzen davon herum. Sollte das nicht ausreichen, ist der Programmentwurf sehr wahrscheinlich fragwürdig.
friedduck
User
Beiträge: 76
Registriert: Montag 23. Juli 2012, 20:41

kbr hat geschrieben:
friedduck hat geschrieben:es soll ein globaler Wertespeicher werden
Erstelle eine Klasse und reiche Instanzen davon herum. Sollte das nicht ausreichen, ist der Programmentwurf sehr wahrscheinlich fragwürdig.
Das würde mir schon genügen. Wie kann ich das Bewerkstelligen, also die Instanzen rumreichen?

@Blackjack:
Bei den Daten handelt es sich um Einstellungen z.B von einem SMTP Server, IP Adresse, Port u.s.w. Die Wollte ich dann gleich beim Programmstart
irgendwo ablegen um dann im späteren Programmablauf darauf zugreifen zu können.

Wie würdest du denn das Problem angehen?
BlackJack

@friedduck: Solche Daten könnte man in einem Modul ablegen oder in einer Konfigurationsdatei. Ich tendiere zum letzteren im JSON-Format. Die lädt man dann von der Hauptfunktion aus und übergibt die Werte an die Funktionen und Objekte in denen man sie benötigt.
xeike
User
Beiträge: 83
Registriert: Donnerstag 28. Februar 2013, 09:58

friedduck hat geschrieben:Bei den Daten handelt es sich um Einstellungen z.B von einem SMTP Server, IP Adresse, Port u.s.w.
Ich würde ein dict nehmen. Und folgendermaßen kannst du das dict rumreichen:

Code: Alles auswählen

einstellungen = {'ip':'127.0.0.1', 'server':'www.python-forum.de'}
>>> einstellungen
{'ip': '127.0.0.1', 'server': 'www.python-forum.de'}
>>> einstellungen['ip']
'127.0.0.1'
>>> def foo( meine_einstellungen ):
...   print( meine_einstellungen )
... 
>>> foo( einstellungen )
{'ip': '127.0.0.1', 'server': 'www.python-forum.de'}
Viele Grüße

Xe
BlackJack

@xeike: Das ist IMHO unschön solange nicht wirklich alle Werte von `foo()` auch benötigt werden. Und dann wäre es lesbarer wenn die Funktionssignatur nicht nur aus so einem allgemeinen Argument `meine_einstellungen` bestehen würde.
xeike
User
Beiträge: 83
Registriert: Donnerstag 28. Februar 2013, 09:58

BlackJack hat geschrieben:@xeike: Das ist IMHO unschön solange nicht wirklich alle Werte von `foo()` auch benötigt werden. Und dann wäre es lesbarer wenn die Funktionssignatur nicht nur aus so einem allgemeinen Argument `meine_einstellungen` bestehen würde.
Die Kritik verstehe ich nicht.

* Ob oder ob nicht alle Elemente vom dict "einstellungen" gebraucht werden, ist zunächst unerheblich. Der OP wollte nur wissen, wie man Instanzen durch die Gegend reicht.

* dict ist der kleinste Datentyp, der sauber auf seine Elemente per Namen zugreifen kann, ohne weitere Module zu benutzen oder kompliziertere Sprachstrukturen zu bemühen oder gar "magic numbers" einzuführen.

* Störst du dich bei der funktion "foo()" daran, dass die Argumente nicht als Keywords vorliegen?

In dem Fall hilft dem OP vielleicht:

Code: Alles auswählen

def bar( ip="0.0.0.0", server="ww.example.org" ):
...   print( ip, server )
... 
>>> bar()
0.0.0.0 ww.example.org
>>> bar( *einstellungen )
ip server
>>> bar( **einstellungen )
127.0.0.1 ww.python-forum.de
Na, mal sehen.
BlackJack

@xeike: Ich störe mich daran das so alle Einstellungen als „blob” überall herum gereicht werde. Das ist nicht besser als das ganze global zu machen. Das ist weder lesbar, noch nachvollziehbar.
Benutzeravatar
kbr
User
Beiträge: 1487
Registriert: Mittwoch 15. Oktober 2008, 09:27

BlackJack hat geschrieben:Ich störe mich daran das so alle Einstellungen als „blob” überall herum gereicht werde.
Das stimmt natürlich und eine Klasse als reiner Attributcontainer macht die Sache auch nicht besser. Sie sollte dann bspw. auch Methoden zur Persistenz haben; so könnte sie auch kurzlebig eingesetzt und an anderer Stelle wieder mit den gespeicherten Werten neu instanziiert werden. Ist aber nur eine Idee — je nach Einsatzzweck gibt es sicher auch bessere oder gar einfachere Möglichkeiten.
@friedduck: Das "herumreichen" von Objekten erfolgt genauso wie bei allen anderen Variablen/Labels.
friedduck
User
Beiträge: 76
Registriert: Montag 23. Juli 2012, 20:41

Hallo an alle und danke für die zahlreichen Antworten,

ich persönlich favorisiere die lösung von kbr, mit einer Klasse, so könnte ich noch ein paar Methoden reinnehmen um z.B den SMTP Server abzufragen.
Wie mache ich denn meine Klasse persistent? Wahrscheinlich so wie in meinem Anfangsbeitrag?

Code: Alles auswählen

class Testklase(object):
  def __init__(self):
    self.wert1 = 'wert1'
    self.wert2 = 'wert2'
xeike
User
Beiträge: 83
Registriert: Donnerstag 28. Februar 2013, 09:58

Da du ja nur eine Instanz benötigst, könntest du ein Singleton nehmen:
siehe: http://www.python.org/dev/peps/pep-0318/#examples

Zum Thema Persistenz siehe z. B.
http://docs.python.org/3.3/library/shelve.html

Xe
friedduck
User
Beiträge: 76
Registriert: Montag 23. Juli 2012, 20:41

Hallo xeike,
sind die Singletons nicht verrufen?
http://lucumr.pocoo.org/2009/7/24/singl ... in-python/
Benutzeravatar
cofi
Python-Forum Veteran
Beiträge: 4432
Registriert: Sonntag 30. März 2008, 04:16
Wohnort: RGFybXN0YWR0

Ja, wenn, sollte man das Borg-Pattern benutzen. Man kann es sich aber auch einfach machen und einfach nur _ein_ Exemplar erzeugen, das funktioniert wunderbar, denn Python-Module sind natuerliche Singletons.
friedduck
User
Beiträge: 76
Registriert: Montag 23. Juli 2012, 20:41

Man kann es sich aber auch einfach machen und einfach nur _ein_ Exemplar erzeugen
Wie meinst du das?

Abgesehen davon, glaube ich, das mein Codedesign / Strukturierung nicht optimal ist. Die ganzen importe bringen mich echt um den Verstand,
das kann nicht im Sinne des Erfinders sein ( oh Guido...).

Also zurück zum Anfang...
BlackJack

@friedduck: Na man erzeugt nur ein Exemplar. Und nicht mehr als eins. Nicht, zwei. Nicht drei. Nur eins eben. Auf keinen Fall mehr. Das lässt man einfach bleiben. Und gut ist. :-)
friedduck
User
Beiträge: 76
Registriert: Montag 23. Juli 2012, 20:41

BlackJack hat geschrieben:@friedduck: Na man erzeugt nur ein Exemplar. Und nicht mehr als eins. Nicht, zwei. Nicht drei. Nur eins eben. Auf keinen Fall mehr. Das lässt man einfach bleiben. Und gut ist. :-)
:D
Aber das wäre ja völlig gegen den Grundsatz "Viel, hilft auch viel!" :wink:
Antworten