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
Datenspeicherung unabhängig machen - Factory?
-
- Python-Forum Veteran
- Beiträge: 16025
- Registriert: Freitag 20. Juni 2003, 16:30
- Kontaktdaten:
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:
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
My god, it's full of CARs! | Leonidasvoice vs (former) Modvoice
-
- Python-Forum Veteran
- Beiträge: 16025
- Registriert: Freitag 20. Juni 2003, 16:30
- Kontaktdaten:
Nein, das machst du dann so:
Es gibt praktischerweise den ConfigParser der INI-Dateien parsen kann. Sehr nützlich in diesem Fall.
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
My god, it's full of CARs! | Leonidasvoice vs (former) Modvoice
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.
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.
Code: Alles auswählen
def FactoryBuilder(id):
if id == "ini":
return IniPersistance()
elif id == "db":
return DbPersistance()
else:
raise ValueError("Unknown id")
Code: Alles auswählen
def FactoryBuilder(id):
return globals()[id]
Zuletzt geändert von Joghurt am Sonntag 28. Mai 2006, 23:27, insgesamt 3-mal geändert.
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 ?
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 ?
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?
vielen dank im voraus
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.
-
- Python-Forum Veteran
- Beiträge: 16025
- Registriert: Freitag 20. Juni 2003, 16:30
- Kontaktdaten:
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'
My god, it's full of CARs! | Leonidasvoice vs (former) Modvoice
- gerold
- Python-Forum Veteran
- Beiträge: 5555
- Registriert: Samstag 28. Februar 2004, 22:04
- Wohnort: Oberhofen im Inntal (Tirol)
- Kontaktdaten:
Hi Leonidas!Leonidas hat geschrieben:Code: Alles auswählen
# eine möglichkeit, aber eher unpythonic und daher eher abzuraten hasattr(os, 'name')
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
http://halvar.at | Kleiner Bascom AVR Kurs
Wissen hat eine wunderbare Eigenschaft: Es verdoppelt sich, wenn man es teilt.
Wissen hat eine wunderbare Eigenschaft: Es verdoppelt sich, wenn man es teilt.
-
- Python-Forum Veteran
- Beiträge: 16025
- Registriert: Freitag 20. Juni 2003, 16:30
- Kontaktdaten:
Ich stütze es auf eines meiner Lieblings-Python-Paradigmen, EAFP: Easier to ask for forgiveness than permission.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?
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: YMMVPython 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.
My god, it's full of CARs! | Leonidasvoice vs (former) Modvoice
- gerold
- Python-Forum Veteran
- Beiträge: 5555
- Registriert: Samstag 28. Februar 2004, 22:04
- Wohnort: Oberhofen im Inntal (Tirol)
- Kontaktdaten:
Hi Leonidas!Leonidas hat geschrieben:Ich stütze es auf eines meiner Lieblings-Python-Paradigmen, EAFP: Easier to ask for forgiveness than permission.
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
http://halvar.at | Kleiner Bascom AVR Kurs
Wissen hat eine wunderbare Eigenschaft: Es verdoppelt sich, wenn man es teilt.
Wissen hat eine wunderbare Eigenschaft: Es verdoppelt sich, wenn man es teilt.
-
- Python-Forum Veteran
- Beiträge: 16025
- Registriert: Freitag 20. Juni 2003, 16:30
- Kontaktdaten:
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.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.
Das war nur ein beispiel um hasattr() und AttributeError zu demonstrieren.bot hat geschrieben:versteh ich nicht ganz. warum os.name? wo gebe ich da das file an oder die function?
Nein, weil das import-Statement keinen Rückgabewert hat und somit gibts einen SyntaxError.bot hat geschrieben:dann müsste also
a.setattr( from x import foo )
gehen.
Ungetestet:
Code: Alles auswählen
import x
try:
x.foo()
x.bar()
except AttributeError:
a = A()
a.foo()
a.bar()
My god, it's full of CARs! | Leonidasvoice vs (former) Modvoice
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
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