Seite 1 von 2

Telefonbuch aus byte of Python

Verfasst: Donnerstag 21. Mai 2009, 16:22
von Cenz
Hallo

Ich fange gerade an Python zu lernen, ist meine erste Sprache.
Ich habe "Byte of Python" gelesen und habe dann versucht das Telefonbuch als Übung zu programmieren, aber es will einfach nicht die gespeicherten Daten anzeigen.

Ich würde mich freuen, wenn mir jemand helfen könnte

Code: Alles auswählen

#!/usr/bin/python
# Filename: telefonbuch.py

import pickle


Personenfile = 'Personen.data'
Personen = {}


print ('1: Person hinzufügen')
print ('2: Zeige Personen')

class Person:
	'''Representiert jede Person'''
	def __init__(self, name, number):
		self.name = name
		self.number = number
		print( 'Person: {0}'.format(self.name))

	def tell(self):
		'''Erzählt ihre details'''
		print('Name:"{0}" Nummer:"{1}"\n'.format(self.name, self.number), end="")


do = input('Was möchtest du tun')


def addPerson():
	name = input('Wie ist ihr name? ')
	number = input('Wie ist ihre Nummer? ')
	name = Person(name, number)
	Personen[name] = ''
	f = open(Personenfile, 'ab')
	pickle.dump(Personen, f) # dump das objekt zum file
	f.close()

def zeigePersonen():
	f = open(Personenfile, 'rb')
	Personenspeicher = pickle.load(f) # lädt das object von dem file
	print(Personenspeicher)

if do == '1':
	addPerson()

if do == '2':
	zeigePersonen()

Verfasst: Donnerstag 21. Mai 2009, 16:35
von cofi
Du bekommst keine Fehlermeldungen?
Die Zeilen 33 und 34 sehen für mich so aus, als würdest du das Dictionary mit ungültigen Schlüsseln füttern - auch sehen die für mich so aus als wär das gewolltes Verhalten ;)

Aber noch ein paar Worte zum Stil:
1. Es gibt das `with`-Statement, damit kann man übrigens auch nicht mehr vergessen die Objekte zu schliessen ;):

Code: Alles auswählen

with open(Personenfile, "ab") as f:
    pickle.dump(Personen, f)
2. Schau dir mal [wiki]PEP 8 (Übersetzung)[/wiki] oder das Orginal an

Verfasst: Donnerstag 21. Mai 2009, 16:51
von Cenz
In Byte of Python steht man solle ein dictionary erzeugen um darin die Objekte für die Personen abzulegen.
Das ist der einzige weg den ich gefunden habe. Fehlermeldungen bekomme ich keine, nur wenn ich die Personendaten abrufen will:
1: Person hinzufügen
2: Zeige Personen
Was möchtest du tun2
{<__main__.Person object at 0x7f0852210f90>: ''}

Ich werde mir mal gleich den Artikel durchlesen, danke.
Ich fände es trotzdem schön, wenn mir jemand meinen Fehler genau erklärt.

Verfasst: Donnerstag 21. Mai 2009, 17:52
von BlackJack
@Cenz: Was hättest Du denn erwartet da zu sehen? Du bekommst genau das zurück was Du in das Dictionary reingesteckt hast. Eine Person als Schlüssel unter dem eine leere Zeichenkette gespeichert ist. Was irgendwo reichlich sinnfrei ist.

Verfasst: Donnerstag 21. Mai 2009, 17:58
von Rebecca
Cenz hat geschrieben:{<__main__.Person object at 0x7f0852210f90>: ''}
Hier wird dir ja die Person angezeigt. Da Python natuerlich nicht weiss, was eine Person genau ist, weiss es auch nicht, was genau es anzeigen soll, damit es fuer dich verstaendlich ist. So wird nur der Objekttyp und die Speicheradresse angezeigt.

Moechtest du das aendern, solltest du die __str__-Methode des Person-Klasse ueberschreiben, sodass sie einen vernuenftigen String zurueckgibt, z.B.:

Code: Alles auswählen

def __str__(self):
    return "%s %s" % (self.number, self.name)
Bitte benenne deine Variablennamen (in diesem Fall Personenspeicher) mit Kleinbuchstaben, so ist es sehr verwirrend.

EDIT: Ich hab nicht richtig hingeschaut, BlackJack hat natuerlich Recht. Mein Vorschlag hilft nur, wenn du dir das Person-Objekt selbst ausgeben laesst, nicht ein Dictionary mit einer Person drin.

Verfasst: Donnerstag 21. Mai 2009, 18:07
von Cenz
Also, die Anleitung sieht folgendermaßen aus (Byte of Python)
"Create a class to represent the person's information. Use a dictionary to store person
objects with their name as the key. Use the pickle module to store the objects
persistently on your hard disk. Use the dictionary built-in methods to add, delete and
modify the persons."

Ich habe mein bestes gegeben, das umzusetzen.

Ich habe mich auch schon gewundert was ich als value im dict angeben soll. Wenn ich dort die Nummer angeben würde könnte ich doch nur eine Information zur Person speichern, oder?

Ich würde mich freuen, wenn mir jemand zeigt wie man es besser macht.

Verfasst: Donnerstag 21. Mai 2009, 18:20
von Leonidas
Ich denke der meint da dass der Name als String der Key sein soll, der Value soll das Personenobject sein.

Verfasst: Donnerstag 21. Mai 2009, 18:25
von BlackJack
Du sollst den *Namen* als Schlüssel nehmen. Was hast Du genommen? Und wenn Du den Namen nimmst, was sollte dann wohl der Wert sein?

So ein Dictionary bildet Schlüssel auf Werte ab. Wenn man in einem Telefonbuch einen Namen nachschlägt, was möchte man dann finden?

Ausserdem solltest Du immer das gesamte Telefonbuch, also in diesem Fall das Dictionary laden und speichern und nicht Objekte an die Datei anhängen. Dann müsstest Du nämlich auch mühsam solange `load()` aufrufen bis alle einzelnen Objekte wieder ausgelesen sind, und das Löschen von Einträgen wird auch viel komplizierter.

Verfasst: Donnerstag 21. Mai 2009, 18:38
von Cenz
Ok, verstanden.
Kann in einen dict ein key mehr als einen value haben?
Ansonsten könnte ich nicht mehr Informationen als die Nummer angeben was wäre dann mit der email und so weiter. Wozu brauche ich dann überhaupt Klassen wenn ich doch sowieso nur Name und Nummer verwende?

Verfasst: Donnerstag 21. Mai 2009, 18:45
von Leonidas
Cenz hat geschrieben:Kann in einen dict ein key mehr als einen value haben?
Nein. Wenn man mehr als einen einzelnen Wert abspeichern will nimmt man Listen oder Objekte.
Cenz hat geschrieben:Ansonsten könnte ich nicht mehr Informationen als die Nummer angeben was wäre dann mit der email und so weiter. Wozu brauche ich dann überhaupt Klassen wenn ich doch sowieso nur Name und Nummer verwende?
Klassen brauchst du wenn du noch weitere Informationen abspeichern willst. Wie etwa die E-Mail-Adresse.

Verfasst: Donnerstag 21. Mai 2009, 18:49
von Cenz
danke :)

Wie muss denn jetzt meine

Code: Alles auswählen

def addPerson():
aussehen damit es funktioniert.

Verfasst: Donnerstag 21. Mai 2009, 19:00
von cofi
Wie schon gesagt: Zeile 33+34 sind der Knackpunkt.
Das solltest du so ändern:

Code: Alles auswählen

Personen[name] = Person(name, number)

Verfasst: Donnerstag 21. Mai 2009, 19:07
von Cenz
Also nach der Änderung wird die Meldung nur länger:
{<__main__.Person object at 0x7f53a9d3cf90>: <__main__.Person object at 0x7f53a9d3ced0>}

Verfasst: Donnerstag 21. Mai 2009, 19:26
von BlackJack
Du musst als Schlüssel den *Namen* nehmen, nicht die ganze `Person`.

Verfasst: Donnerstag 21. Mai 2009, 19:38
von Cenz
Aber wie mache ich das. Das einzige was mir einfällt ist dort name einzugeben.
Ich weiß, das ist nicht nur der Name sondern auch gleichzeitig die Person, wie trenne ich das.?

Verfasst: Donnerstag 21. Mai 2009, 20:28
von BlackJack
In dem Du den Namen `name` nicht an das `Person`-Objekt bindest. Einen Namen innerhalb einer Funktion für so unterschiedliche Typen zu "recyclen" ist sowieso keine gute Idee, weil das bei längeren Programmen nur Verwirrung stiftet wenn man immer ganz genau hingucken muss an welcher Stelle nun welcher Typ an den Namen gebunden ist. `name` war ja *vorher* wirklich mal an den Namen gebunden.

Verfasst: Donnerstag 21. Mai 2009, 20:31
von cofi
Cenz hat geschrieben:Also nach der Änderung wird die Meldung nur länger:
{<__main__.Person object at 0x7f53a9d3cf90>: <__main__.Person object at 0x7f53a9d3ced0>}
Du sollst auch nicht Zeile 34, sondern 33+34 durch meine Zeile ersetzen.

Re: Telefonbuch aus byte of Python

Verfasst: Freitag 22. Mai 2009, 10:34
von numerix
Cenz hat geschrieben:Ich fange gerade an Python zu lernen, ist meine erste Sprache.
Das war dein erster Satz in diesem Thread und vielleicht wäre es nicht das schlechteste, einen Schritt zurück zu gehen, und zunächst einmal die Konstruktion eigener Klassen wegzulassen.

Experimentiere doch erst mal auf einer "niedrigeren Ebene" mit Dictionaries, etwa so:

Code: Alles auswählen

telefonbuch = {}
while True:
	name = input("Gib deinen Nachnamen ein: ")
	if name == "":
		break
	vorname = input("Dein Vorname: ")
	stadt = input("Dein Wohnort: ")
	telefon = input("Deine Telefonnummer: ")
	telefonbuch[name] = {"Vorname":vorname, "Stadt":stadt, "Telefon":telefon}

for name in telefonbuch:
	eintrag = telefonbuch[name]
	print("\nEintrag für {0} {1}:".format(eintrag["Vorname"], name))
	print("Wohnort: {0}  Telefon: {1}".format(eintrag["Stadt"], eintrag["Telefon"]))

Verfasst: Freitag 22. Mai 2009, 13:58
von Cenz
cofi hat geschrieben:
Cenz hat geschrieben:Also nach der Änderung wird die Meldung nur länger:
{<__main__.Person object at 0x7f53a9d3cf90>: <__main__.Person object at 0x7f53a9d3ced0>}
Du sollst auch nicht Zeile 34, sondern 33+34 durch meine Zeile ersetzen.
Habe ich auch anschließend gemacht, hat aber nicht viel an der Meldung geändert.

Danke für die viele Hilfe, ich glaube ich lerne noch ein bisschen bevor ich mich wieder an das Projekt Wage. :D

Verfasst: Freitag 22. Mai 2009, 15:22
von cofi
Das kann nicht sein, denn in Zeile 33 überschreibst du `name` mit dem `Person`-Objekt was eben zu dem seltsamen und unbrauchbaren Dictionary-Mapping führt.