Dann reden wir von einem anderem Quelltext. In dem, den ich verlinkt habe wird keine Adresse im Adressbuch gespeichert.
Was `Adressbuch_GUI.vor()` bedeuten *soll* ist klar, mir ist nicht klar warum Du denkst der Code der dort steht würde das tun. Wieso `anzahl`!? Was ist der Sinn der Schleife? Wo kommt `entry` her?
Ein Adressbuch mit Tkinter
-
- Python-Forum Veteran
- Beiträge: 16025
- Registriert: Freitag 20. Juni 2003, 16:30
- Kontaktdaten:
Fehler sind nicht ausgeschlossen, denn ich habe den Code in paste-Fenster geschrieben ohne ihn zu testen - mich hätten auch IndentationErrors nicht gewundert...kaytec hat geschrieben:Ich habe einen kleine Fehler gefunden. Es fehlt ein Unterstrich in self.custom_attrs.append(key).
Deine Beschreibung von OOP habe ich, ähnlich wie BlackJack, nicht verstanden
My god, it's full of CARs! | Leonidasvoice vs (former) Modvoice
Hallo BlackJack !!
Er tut mal das was ich möchte er löscht die Einträge aus den Entrys und fügt dort die neue Adresse ein. Ich erzeuge die Entrys mit einer Schleife, damit ich nicht alle ausformulieren muß. Damit ich die einzelnen Entrys ansprechen kann, übergebe ich sie in die Liste 'self.adressbuch_entry'. Aus dieser Liste hole ich sie mir wieder und lösche den Inhalt und übergebe einen neuen Inhalt, den der nächsten Adresse 'self.adresse = self.iadressen.next()'. Self.adresse ist nun eine Liste und aus der holen ich mir mit entry.insert(0, self.adresse[anzahl] diesen neuen Inhalt. Funktioniert eigentlich recht gut - hatte deswegen gedacht es ist so richtig.
gruss frank
Er tut mal das was ich möchte er löscht die Einträge aus den Entrys und fügt dort die neue Adresse ein. Ich erzeuge die Entrys mit einer Schleife, damit ich nicht alle ausformulieren muß. Damit ich die einzelnen Entrys ansprechen kann, übergebe ich sie in die Liste 'self.adressbuch_entry'. Aus dieser Liste hole ich sie mir wieder und lösche den Inhalt und übergebe einen neuen Inhalt, den der nächsten Adresse 'self.adresse = self.iadressen.next()'. Self.adresse ist nun eine Liste und aus der holen ich mir mit entry.insert(0, self.adresse[anzahl] diesen neuen Inhalt. Funktioniert eigentlich recht gut - hatte deswegen gedacht es ist so richtig.
gruss frank
Okay der Code tut doch das was er soll. Ich bin blöd. Oder kann Deinen Code nicht lesen. Der ist so "anders" das er mich verwirrt.
Schön ist das trotzdem nicht. `anzahl` ist keine Anzahl sondern ein Index. Da hätte ich eher `zip()` benutzt um die Elemente der Adresse mit den `Entry`\s zusammen zu bringen. Aber `Adressen` Objekte speichern keine Adressen. Oder das passiert auch wieder auf eine komische Art und ich versteh's nicht.
Schön ist das trotzdem nicht. `anzahl` ist keine Anzahl sondern ein Index. Da hätte ich eher `zip()` benutzt um die Elemente der Adresse mit den `Entry`\s zusammen zu bringen. Aber `Adressen` Objekte speichern keine Adressen. Oder das passiert auch wieder auf eine komische Art und ich versteh's nicht.
@BlackJack !
Das Speicher geht auch. 'self.adress_buch = Adressbuch(self.feldnamen)' habe ich aus Objekorientierte Progammierung mit Python von Michael Wiegand. Der macht es so bei einem Vokabeltrainer. Bei ihm würde es so aussehen (galube ich mal ?) self.a = Adressbuch(self.feldnamen)'. Das finde ich auch nicht so schön und deswegen habe ich den Namen ausformuliert. Wie ich es verstanden habe macht er es ,damit er beim Laden oder Speichern nicht 'Adressbuch(self.feldnamen).laden()' schreiben müsste, sondern damit man schreiben kann: 'self.a.laden()'.
Habe mein Programm mal mit Deinem Ansatz ohne Tkinter gemacht, damit du mein Problem evt. verstehst.
Würde ich es ohne 'def__len' und 'def__iter' schreiben und einfach adressen = Adressbuch().laden() in die main() Funktion schreiben, dann hätte ich kein Probleme mit dem Eintragen von neuen Adressen. Deswegen sieht es für mich irgendwie unnötig aus, diese Methoden zu formulieren. Auch eine Suche in der Klasse Adressbuch ist doch 'blödsinnig', da ich beim Eintragen einer neuen Adresse nach dieser gar nicht suchen kann. Ich müsste die Adressen speichern und neu laden - oder ?
hast du es so gemeint ?
gruss und dank frank
Das Speicher geht auch. 'self.adress_buch = Adressbuch(self.feldnamen)' habe ich aus Objekorientierte Progammierung mit Python von Michael Wiegand. Der macht es so bei einem Vokabeltrainer. Bei ihm würde es so aussehen (galube ich mal ?) self.a = Adressbuch(self.feldnamen)'. Das finde ich auch nicht so schön und deswegen habe ich den Namen ausformuliert. Wie ich es verstanden habe macht er es ,damit er beim Laden oder Speichern nicht 'Adressbuch(self.feldnamen).laden()' schreiben müsste, sondern damit man schreiben kann: 'self.a.laden()'.
Habe mein Programm mal mit Deinem Ansatz ohne Tkinter gemacht, damit du mein Problem evt. verstehst.
Code: Alles auswählen
#! /usr/bin/env python
# -*- coding: utf-8 -*-
class Adressbuch(object):
def __init__(self):
self.adressen = self.laden()
def __len__(self):
return len(self.adressen)
def __iter__(self):
return iter(self.adressen)
def laden(self):
adressen = (('Max', 'Muster', 'Maxstr. 12', '1 Maxhausen', '012345678'),
('Tuxi', 'Tux', 'Tuxstr. 21','2 Tuxhausen', '023456734'))
return adressen
def speichern(self, adressen):
pass
def suchen(adressen):
suchergebnis = list()
suche = raw_input('Suche: ')
for adresse in adressen:
for eintrag in adresse:
if suche.upper() in eintrag.upper():
suchergebnis.append(adresse)
break
for adresse in suchergebnis:
print adresse
def eintragen(adressen):
#hier würde ich es mit adressen.append(neue_adresse) versuchen !
#das geht nicht !
pass
def ausgeben(adressen):
for adresse in adressen:
print adresse
print 'Im Adressbuch befinden sich ' + str(len(adressen)) + ' Adressen'
def speichern(adressen):
Adressbuch().speichern(adressen)
def main():
adressen = Adressbuch()
auswahl_zu_funktion = { 'S': suchen,
'N': eintragen,
'A': ausgeben,
'E': speichern }
while True:
print
print '____(S)uche mach Adresse_____________'
print '____(N)eue Adresse eintragen_________'
print '____(A)lle Adresse ausgeben__________'
print '____(E)nde___________________________'
print
auswahl = raw_input('Auswahl:').upper()
try:
funktion = auswahl_zu_funktion[auswahl]
except KeyError:
continue
funktion(adressen)
if auswahl == 'E':
break
if __name__ == '__main__':
main()
hast du es so gemeint ?
Code: Alles auswählen
def vor(self):
self.adresse = self.iadressen.next()
for entry, eintrag in zip(self.adressbuch_entry, self.adresse):
entry.delete(0, END)
entry.insert(0, eintrag)
Hallo !!
Die Adressen sollten keine Tulpe, sondern Liste sein !
gruss frank
Die Adressen sollten keine Tulpe, sondern Liste sein !
Code: Alles auswählen
adressen = [['Max', 'Muster', 'Maxstr. 12', '1 Maxhausen', '012345678'],
['Tuxi', 'Tux', 'Tuxstr. 21','2 Tuxhausen', '023456734']]
Du hast OOP nicht verstanden. Und ich weiss echt nicht wie man das noch erklären kann. Wir hängen an dem Thema nun ja schon ein klein wenig länger.
Eine Klasse vereint Daten und Methoden die zusammengehören zu einem Objekt. Dabei sollte man versuchen die Daten zu kapseln, dass heisst das von aussen nicht direkt darauf zugegriffen wird. So dass man die Datenstrukturen in dem Objekt verändern kann, solange nach aussen die Schnittstelle gleich bleibt.
Die Daten in einem Adressbuch sind die Adressen. Die sollten weder von `Adressbuch.laden()` direkt nach draussen gegeben werden, noch von `Adressbuch.speichern()` als Argument erwartet werden. Wenn ich `speichern()` auf einem `Adressbuch`-Objekt aufrufe, dann *enthält* dieses `Adressbuch` doch schon Adressen! Und genau die sollten dann auch gespeichert werden.
`suchen()` und `eintragen()` gehören auch als Methoden zu einem Adressbuch allerdings ohne Benutzerinteraktion. Eine `suchen()`-Methode muss unter Umständen wissen, wie die Adressen intern im `Adressbuch` gespeichert sind, dass geht aussen niemanden etwas an. Bei einem guten Entwurf kann man die Speicherung der Adressen im `Adressbuch` von einer Liste in ein Dictionary, eine Baumstruktur oder gar eine SQL-Datenbank umstellen, ohne das Quelltext ausserhalb der `Adressbuch`-Klasse verändert werden muss.
Der Kommentar bei `eintragen()` ist so ein Punkt der mich ein wenig ratlos macht. Dass das so nicht geht, sollte eigentlich klar sein.
Und mach Die mal klar was bei `speichern()` passiert und wie unsinnig das ist.
Eine Klasse vereint Daten und Methoden die zusammengehören zu einem Objekt. Dabei sollte man versuchen die Daten zu kapseln, dass heisst das von aussen nicht direkt darauf zugegriffen wird. So dass man die Datenstrukturen in dem Objekt verändern kann, solange nach aussen die Schnittstelle gleich bleibt.
Die Daten in einem Adressbuch sind die Adressen. Die sollten weder von `Adressbuch.laden()` direkt nach draussen gegeben werden, noch von `Adressbuch.speichern()` als Argument erwartet werden. Wenn ich `speichern()` auf einem `Adressbuch`-Objekt aufrufe, dann *enthält* dieses `Adressbuch` doch schon Adressen! Und genau die sollten dann auch gespeichert werden.
`suchen()` und `eintragen()` gehören auch als Methoden zu einem Adressbuch allerdings ohne Benutzerinteraktion. Eine `suchen()`-Methode muss unter Umständen wissen, wie die Adressen intern im `Adressbuch` gespeichert sind, dass geht aussen niemanden etwas an. Bei einem guten Entwurf kann man die Speicherung der Adressen im `Adressbuch` von einer Liste in ein Dictionary, eine Baumstruktur oder gar eine SQL-Datenbank umstellen, ohne das Quelltext ausserhalb der `Adressbuch`-Klasse verändert werden muss.
Der Kommentar bei `eintragen()` ist so ein Punkt der mich ein wenig ratlos macht. Dass das so nicht geht, sollte eigentlich klar sein.
Und mach Die mal klar was bei `speichern()` passiert und wie unsinnig das ist.
@ BlackJack !
Welches Speichern meinst du jetzt ? Da wo ich 'pass' stehen habe ? Das ist doch nur, damit ich keine Fehlermeldung bekomme. Das so das Speichern nicht geht ist schon klar!
Das ich OOP falsch mache ist mir schon klar. Nur alles was man so findet ist sehr allgemein gehalten. Für dir Umzusetzung in ein konkretes Beispiel bin ich leider zu doof!
Deine Beschreibung der OOP habe ich jetzt so ungefähr verstanden
Würde ich (kaytec) jetzt versuchen mit einer Klasse. mittels einer anderen Klasse, in Interaktion zu treten, würde ich versuchen eine "Kommunikation" aufzubauen. Da mache ich ja irgendwie immer meine Fehler. - oder ? Ich kann das Gelesene nicht so richtig umsetzen - würde ich als CodeQuäler sagen.
gruss und dank frank
Welches Speichern meinst du jetzt ? Da wo ich 'pass' stehen habe ? Das ist doch nur, damit ich keine Fehlermeldung bekomme. Das so das Speichern nicht geht ist schon klar!
Das ich OOP falsch mache ist mir schon klar. Nur alles was man so findet ist sehr allgemein gehalten. Für dir Umzusetzung in ein konkretes Beispiel bin ich leider zu doof!
Deine Beschreibung der OOP habe ich jetzt so ungefähr verstanden
Würde ich (kaytec) jetzt versuchen mit einer Klasse. mittels einer anderen Klasse, in Interaktion zu treten, würde ich versuchen eine "Kommunikation" aufzubauen. Da mache ich ja irgendwie immer meine Fehler. - oder ? Ich kann das Gelesene nicht so richtig umsetzen - würde ich als CodeQuäler sagen.
gruss und dank frank
-
- Python-Forum Veteran
- Beiträge: 16025
- Registriert: Freitag 20. Juni 2003, 16:30
- Kontaktdaten:
Neion, das andere, das Modulglobale. Du erstellst darin eine *leere* Instanz von Adressbuch und speicherst sie sofort. Damit wird also ein absolut leeres Adressbuch gespeichert. Das bringt absolut gar nichts.kaytec hat geschrieben:Welches Speichern meinst du jetzt ? Da wo ich 'pass' stehen habe ? Das ist doch nur, damit ich keine Fehlermeldung bekomme. Das so das Speichern nicht geht ist schon klar!
My god, it's full of CARs! | Leonidasvoice vs (former) Modvoice
@Leonidas: Es wird keine leere Instanz erzeugt, es ist noch viel sinnloser: Beim erzeugen einer Instanz wird ja erst einmal das alte Adressbuch noch einmal geladen und dann wird speichern mit Adressen als Argument aufgerufen. Und da meinte ich dann schon `Adressbuch.speichern()`. Das sollte die Adressen nicht von aussen bekommen.
@BlackJack und Leonidas !
Das Speichern ist so ein Problem!
Ich habe jetzt eine neue Adresse in meinem 'Adressbuch_Gui' erzeugt. Die möchte ich jetzt speichern. Das ich sie ausserhalb der Klasse Adressbuch erzeuge wird schon mal falsch sein. WIe mache ich es den nun richtig. Ich muss irgendwie eine neue Adresse hinzubekommen, denn sonnst würde ein Adressbuch, das man mit Daten befüllen kann keinen Sinn machen - oder? Wie füge ich in das vorhandene oder evt. leere Adressbuch nach OOP, denn Daten ein.
gruss und dank frank
Das Speichern ist so ein Problem!
Ich habe jetzt eine neue Adresse in meinem 'Adressbuch_Gui' erzeugt. Die möchte ich jetzt speichern. Das ich sie ausserhalb der Klasse Adressbuch erzeuge wird schon mal falsch sein. WIe mache ich es den nun richtig. Ich muss irgendwie eine neue Adresse hinzubekommen, denn sonnst würde ein Adressbuch, das man mit Daten befüllen kann keinen Sinn machen - oder? Wie füge ich in das vorhandene oder evt. leere Adressbuch nach OOP, denn Daten ein.
gruss und dank frank
-
- Python-Forum Veteran
- Beiträge: 16025
- Registriert: Freitag 20. Juni 2003, 16:30
- Kontaktdaten:
Schau dir doch meine Version an: dort hast du ein weiteres Objekt, die Adresse. In der GUI erstellst du eben so eine Adresse-Objekt und Machst eine Funktion etwa Adressbuch.hinzufuegen(self, adresse), dem du die Adresse hinzufügst und dass dann die Adresse abspeichert.kaytec hat geschrieben:Ich habe jetzt eine neue Adresse in meinem 'Adressbuch_Gui' erzeugt. Die möchte ich jetzt speichern. Das ich sie ausserhalb der Klasse Adressbuch erzeuge wird schon mal falsch sein. WIe mache ich es den nun richtig. Ich muss irgendwie eine neue Adresse hinzubekommen, denn sonnst würde ein Adressbuch, das man mit Daten befüllen kann keinen Sinn machen - oder? Wie füge ich in das vorhandene oder evt. leere Adressbuch nach OOP, denn Daten ein.
My god, it's full of CARs! | Leonidasvoice vs (former) Modvoice
Der nächste Versuch !
feldnamen sollten besser übergeben werden - oder?
gruss und dank frank
Code: Alles auswählen
import pickle
class Adressen(object):
feldnamen = ('Name:','Vorname:', 'Strasse:', 'Ort:',
'Festnetz:', 'Handy:','Arbeit:', 'email:',
'Bemerkung:')
def __init__(self, dateiname):
self.adressen = self.laden(dateiname)
def __iter__(self):
return iter(self.adressen)
def __len__(self):
return len(self.adressen)
def hinzufuegen(self, adresse):
self.adressen.append(adresse)
self.adressen.sort()
def loeschen(self, adresse):
self.adressen.remove(adresse)
self.adressen.sort()
def laden(self, dateiname):
try:
datei = file(dateiname, 'r')
except IOError:
adressen = list()
adresse = list()
adresse.extend(''.join(' ' * len(self.feldnamen)))
adressen.append(adresse)
return adressen
adressen = pickle.load(datei)
datei.close()
return adressen
def speichern(self, dateiname):
datei = file(dateiname, 'w')
pickle.dump(self.adressen, datei)
datei.close()
gruss und dank frank
Ein letzer Versucht macht ja beinahe genau so wenig Sinn Warum sollte man mehrere Adressen in einem Objekt "Adressen" zusammenfassen, dass ist doch eigentlich schon das Adressbuch! Ziel ist es ja nicht, das Programm in irgend welche Objekte zu zerlegen, sondern in sinnvolle Objekte, welche man so unter Umständen auch in der Realität verwenden würde.
Hier mal ein sinnvoller Aufbau kurz angerissen:
Der init-Methode von "Adresse" könnte man natürlich auch einfach beliebige Keywords übergeben, so könnte man beliebig viele Eigenschaften zu einer Adresse speichern.
Hier mal ein sinnvoller Aufbau kurz angerissen:
Code: Alles auswählen
import pickle
class Adresse(object):
def __init__(self, name, vorname, strasse, ort, ...):
self.name = name
self.vorname = vorname
self.strasse = strasse
self.ort = ....
class Adressbuch(object):
def __init__(self, adress_datei):
self.adressen = self.load(adress_datei)
def laden(self, adress_datei):
try:
fp = open(adress_datei, "rb")
except IOError:
return []
else:
return pickle.load(fp)
fp.close()
def speichern(self, adress_datei):
fp = open(adress_datei, "wb")
pickle.dump(self.adressen, fp)
fp.close()
def neue_adresse(self, name, vorname, ...):
self.adressen.append(Adresse(name, vorname, ...))
Ignorier den Beitrag von EyDu einfach.
Zu Deinem letzten Versuch: Methoden sollten in der Regel entweder den Zustand des Objekts verändern oder Informationen über den aktuellen Zustand liefern. `laden()` macht das nicht. Wurde aber schon mehrfach erwähnt.
Der Teil in der Ausnahmebehandlung ist sehr komisch und umständlich. Da wird eine Zeichenkette mit Leerzeichen erstellt, die dann zu einer identischen Zeichenkette mit Leerzeichen zeichenweise zusammengesetzt nur um dann in eine Liste mit Leerzeichen wieder auseinandergenommen zu werden. Argh!
Wobei ich sowieso nicht so ganz verstehe warum das Adressbuch einen leeren Datensatz enthalten soll wenn es nicht geladen werden kann.
Die Ausnahmebehandlung ist an der Stelle auch nicht ganz glücklich. Wenn diese Klasse in einem Programm verwendet wird, und der Benutzer einen Dateinamen angeben kann, dann sollte er darüber informiert werden, dass es keine Datei mit diesem Namen gibt und nicht einfach ein leeres Adressbuch bekommen.
Zu Deinem letzten Versuch: Methoden sollten in der Regel entweder den Zustand des Objekts verändern oder Informationen über den aktuellen Zustand liefern. `laden()` macht das nicht. Wurde aber schon mehrfach erwähnt.
Der Teil in der Ausnahmebehandlung ist sehr komisch und umständlich. Da wird eine Zeichenkette mit Leerzeichen erstellt, die dann zu einer identischen Zeichenkette mit Leerzeichen zeichenweise zusammengesetzt nur um dann in eine Liste mit Leerzeichen wieder auseinandergenommen zu werden. Argh!
Wobei ich sowieso nicht so ganz verstehe warum das Adressbuch einen leeren Datensatz enthalten soll wenn es nicht geladen werden kann.
Die Ausnahmebehandlung ist an der Stelle auch nicht ganz glücklich. Wenn diese Klasse in einem Programm verwendet wird, und der Benutzer einen Dateinamen angeben kann, dann sollte er darüber informiert werden, dass es keine Datei mit diesem Namen gibt und nicht einfach ein leeres Adressbuch bekommen.
Danke BlackJack !
Ok - laden muss ich die Adressen doch ! Von Aussen darf ich es nicht in der Klasse auch nicht ?
Das mit der Übergabe einer leeren Liste kommt daher, dass ich bei der Version mit Tkinter eine Fehlermeldung hatte und diese damit aufgehoben hatte. Konnte nichts anzeigen bei einem leeren Adressbuch.
Warum ist das eigentlich mein letzter Versuch ? Hört sich wie eine Drohung an - war ja eigentlich mein nächster Versuch !
gruss frank
Ok - laden muss ich die Adressen doch ! Von Aussen darf ich es nicht in der Klasse auch nicht ?
Das mit der Übergabe einer leeren Liste kommt daher, dass ich bei der Version mit Tkinter eine Fehlermeldung hatte und diese damit aufgehoben hatte. Konnte nichts anzeigen bei einem leeren Adressbuch.
Warum ist das eigentlich mein letzter Versuch ? Hört sich wie eine Drohung an - war ja eigentlich mein nächster Versuch !
gruss frank
-
- Python-Forum Veteran
- Beiträge: 16025
- Registriert: Freitag 20. Juni 2003, 16:30
- Kontaktdaten:
Gratuliere, sieht ähnlich aus, wie mein Versuch kaytec einen sinnvollen Klassenaufbau zu zeigen.EyDu hat geschrieben:Hier mal ein sinnvoller Aufbau kurz angerissen
kaytec, die laden() Funktion soll *nichts* (also nur None) zurückgeben, keine Liste von Adressen sondern den *Zustand* der Klasse ändern. Außerdem, wenn man an irgendeiner Stelle in einer Klasse vordefinierte Variablen brauch, seinen sie None oder leere Listen, dann initialisiert man sie in __init__().
My god, it's full of CARs! | Leonidasvoice vs (former) Modvoice