Seite 1 von 1

Datenspeicherung unabhängig machen - Factory?

Verfasst: Montag 22. Mai 2006, 19:52
von bot
Hi

Wenn ich ein Programm habe und möchte das meine Daten "unabhängig" gespeichert werden, wie mache ich das am besten unter Python?

sprich der Appl. soll es egal sein, ob z.B. Userdaten

- in eine db geschrieben werden
- auf file ebene ( da auch maybe unabhängig z.b. ini oder xml )
- über http zu einem server verschickt werden ( maybe soap )
- ect.

In C++ würde ich das mit ner Abstract Factory Class machen und nur die Schnittstellen definieren.

z.b.

m_user.Save();

Die Save Fkt ist für alle gleich, nur die implementation total anders.

Kann mir da einer ne gute Seite nennen wo ein tolles bsp für sowas ist?

Wäre echt supi :)

Verfasst: Montag 22. Mai 2006, 21:14
von Leonidas
Und was hintert dich daran, genau das su machen? Du definierst einen Basisklasse, definierst sagen wir mal die Funktionen alle als abstrakt (raise NotImplementedError) damit du ein Interface hast, leitest mehrere Klassen ab, die die Persistenz (RDBMS, OODBMS, pickle, INI, XML) implementieren. Los gehts!
Da brauchts auch nicht viel Code für:

Code: Alles auswählen

class BasePersistance(object):
    def __init__(self):
        raise NotImplementedException('Abstract class')

    def save(self):
        raise NotImplementedException('Abstract class')

class PicklePersistance(BasePersistance):
    def __init__(self):
        # pickle Init-Code hier

    def save(self):
        # speichern-Code hier

Verfasst: Montag 22. Mai 2006, 21:21
von bot
Danke

Wie sieht es dann aus wenn ich dies per ini verwalten will?

[IRGENDWAS]
wasdenn=ini

m_wassdenn #ini ist hier drin


BasePersistance( m_wasdenn )

das ist doch jetzt nichtdamit getan oder?

Verfasst: Montag 22. Mai 2006, 21:30
von Leonidas
Nein, das machst du dann so:

Code: Alles auswählen

class IniPersistance(BasePersistance):
    def __init__(self):
        filename = 'name.ini'

    def save(self):
        # hier der code der die Einstellungen in die INI-Datei speichert

    def load(self):
        # hier der code der die Einstellungen mittels ConfigParser ausliest
Es gibt praktischerweise den ConfigParser der INI-Dateien parsen kann. Sehr nützlich in diesem Fall.

Verfasst: Montag 22. Mai 2006, 22:23
von bot
und wo bestimm ich was gemacht wird? da muss es doch eine art "switch" geben, ne? je nachdem was der value der ini ist, muss doch die richtige klasse erstellt werden.

if m = ini:
obj = IniPersistance
elif m = db:
obj = DbPersistance

und dann speichere ich meine werte mit

obj.save()

so ungefähr hab ich mir das vorgestellt

habe noch diese klasse hier gefunden

http://aspn.activestate.com/ASPN/Cookbo ... cipe/86900

in c++ würd ich das so machen

obj = FactoryBuilder("ini")

und das wars.

Verfasst: Dienstag 23. Mai 2006, 10:45
von Joghurt

Code: Alles auswählen

def FactoryBuilder(id):
  if id == "ini":
    return IniPersistance()
  elif id == "db":
    return DbPersistance()
  else:
    raise ValueError("Unknown id")
Oder auch (ungetestet):

Code: Alles auswählen

def FactoryBuilder(id):
  return globals()[id]
Das ist aber gefährlich.

Verfasst: Mittwoch 24. Mai 2006, 14:53
von Mad-Marty
Am besten über eine AbstractFactory dein object instanzieren.

Als Übergabe könnte ich mir einen pfad zu einer .ini vorstellen.

In der __new__ deiner AbstractFactory nutzt du am besten den ConfigParser um dir eine klasse oder eine registry mit classen zu bauen, entweder mittels __meta__ oder setattr.

Ich bevorzuge setattr. (Klassen sind auch objekte)

Dann braucht dein __new__ deiner AbstractFactory nur noch auszuwählen welche echte Klasse instanziert wird, dies zu tun, und das object mit return zurückgeben.

Oder gibts da bessere wege ?

Verfasst: Donnerstag 25. Mai 2006, 09:06
von bot
Es werde es so machen wie Joghurt Bsp.

Aber mal ne Folgefrage.

Ich habe z.b. jetzt ein konkretes Objekt a ( von class A ) und diese hat 2 Methoden foo(), bar()

Ich habe jetzt in einem x.py file eine function bar() drin.

Was ich jetzt machen will ist, von dem Objekt a erst foo dann bar aufrufen, aber ich will immer erst schauen ob in meiner x.py datei es eine gleichnamige function gibt, wenn ja dann nimm diese.

wie würde ich dies machen?

Code: Alles auswählen

from utils import hasOwnMethod
class a
#... some inits for a

# rufe foo auf

if hasOwnMethod( "x.py", "foo" ):    # 1. parameter file, 2. functionsname
  a.setattr( from x import foo ) # wird das so gemacht?
  a.foo
else:
  a.foo           # hier wird das standard genommen

#rufe jetzt bar auf

if hasOwnMethod( "x.py", "bar" ):    # 1. parameter file, 2. functionsname
  a.setattr( from x import bar ) # hier das das aus x.py genommen
  a.bar
else:
  a.bar     

# wie genau müsste hasOwnMethod implementiert sein?
# getattr ist ja für klassen.

vielen dank im voraus

Verfasst: Donnerstag 25. Mai 2006, 10:50
von Leonidas
Was du suchst ist hasattr:

Code: Alles auswählen

import os
# eine möglichkeit, aber eher unpythonic und daher eher abzuraten
hasattr(os, 'name')

# alternativ, und eher pythonic (EAFP):
try:
    print os.name
except AttributeError:
    print 'os.name gibt es nicht'

Verfasst: Donnerstag 25. Mai 2006, 11:08
von gerold
Leonidas hat geschrieben:

Code: Alles auswählen

# eine möglichkeit, aber eher unpythonic und daher eher abzuraten
hasattr(os, 'name')
Hi Leonidas!

Ich habe zwar den Anfang dieses Threads nicht verfolgt, aber warum bezeichnest du "hasattr()" als unpythonic und warum soll man es nicht verwenden? Auf was stützt du deine Aussage?

lg
Gerold
:-)

Verfasst: Donnerstag 25. Mai 2006, 11:42
von Leonidas
gerold hat geschrieben:Ich habe zwar den Anfang dieses Threads nicht verfolgt, aber warum bezeichnest du "hasattr()" als unpythonic und warum soll man es nicht verwenden? Auf was stützt du deine Aussage?
Ich stütze es auf eines meiner Lieblings-Python-Paradigmen, EAFP: Easier to ask for forgiveness than permission.
Python Glossar hat geschrieben:This common Python coding style assumes the existence of valid keys or attributes and catches exceptions if the assumption proves false. This clean and fast style is characterized by the presence of many try and except statements.
Klar, man kann hasattr() verwenden, aber ich denke, dass man mit try-except schneller vorrankommt, wenn man davon ausgeht, dass es diese Attribute gibt, statt erst zu prüfen ob es sie gibt und sie dann erst zu benutzen. Wobei: YMMV :)

Verfasst: Donnerstag 25. Mai 2006, 12:12
von gerold
Leonidas hat geschrieben:Ich stütze es auf eines meiner Lieblings-Python-Paradigmen, EAFP: Easier to ask for forgiveness than permission.
Hi Leonidas!

Ich interpretiere das verlinkte Glossary so: Es gibt **EAFP** und es ist ganz normal, wenn man es in in Python verwendet. Das schließt aber keinesfalls **LBYL** aus und stellt auch keine Empfehlung dar. Ich denke, man soll das verwenden, was in der aktuellen Situation an bequesten ist.

lg
Gerold
:-)

Verfasst: Donnerstag 25. Mai 2006, 12:39
von bot
versteh ich nicht ganz. warum os.name? wo gebe ich da das file an oder die function?

dann müsste also

a.setattr( from x import foo )

gehen. werde es an meinem platz mal ausprobieren.

Verfasst: Donnerstag 25. Mai 2006, 19:23
von Leonidas
gerold hat geschrieben:Ich interpretiere das verlinkte Glossary so: Es gibt **EAFP** und es ist ganz normal, wenn man es in in Python verwendet. Das schließt aber keinesfalls **LBYL** aus und stellt auch keine Empfehlung dar. Ich denke, man soll das verwenden, was in der aktuellen Situation an bequesten ist.
Man kann beides verwenden, klar, jedoch denke ich schon, dass man sich eher an EAFP halten sollte. Wieso? Na, es geht ja nicht nur ums prüfen von Atributen, sondern um die generelle Einstelltung, dass alles funktioniert. Wenn es nicht funktioniert, dann kann man ja immer noch hinterher versuchen, es wieder ins Lot zu bringen. Man kann nicht alle möglichen Fehlerquellen explizit vorher prüfen.
bot hat geschrieben:versteh ich nicht ganz. warum os.name? wo gebe ich da das file an oder die function?
Das war nur ein beispiel um hasattr() und AttributeError zu demonstrieren.
bot hat geschrieben:dann müsste also

a.setattr( from x import foo )

gehen.
Nein, weil das import-Statement keinen Rückgabewert hat und somit gibts einen SyntaxError.

Ungetestet:

Code: Alles auswählen

import x
try:
    x.foo()
    x.bar()
except AttributeError:
    a = A()
    a.foo()
    a.bar()

Verfasst: Freitag 26. Mai 2006, 14:54
von bot
gut, dann werde ich das mit dem try so versuchen, nur was ungeschickt ist, wenn ich 10 fkt habe und es gäbe

1,2,3,5

dann würde er ja bei 4 eine exception werfen und die 5te "überschriebene" fkt nicht verwenden. hmm dann schreibe ich eine extra fkt die schleifenartig das durchgeht