Funktionen richtig formuliert ?

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.
EyDu
User
Beiträge: 4871
Registriert: Donnerstag 20. Juli 2006, 23:06
Wohnort: Berlin

Freitag 20. April 2007, 08:45

Code: Alles auswählen

print adressbuch['Muster Max'][0]
:D

Aber die Einträge über Indizes ansprechen ist immer eine schlechte Idee. Da solltest du dir lieber eine Funktion schreiben, die alle Eintraege ueber einen Namen zusammensammelt.

Dinen zweiten Ansatz im letzten Post solltest du lieber gleich vergessen ;-)
Benutzeravatar
kaytec
User
Beiträge: 544
Registriert: Dienstag 13. Februar 2007, 21:57

Freitag 20. April 2007, 09:38

Danke EyDu !

Ok - ich vergesse ihn ja gerne, doch was ist an dem schlechter ? Die Ausgabe würde ich so gestalten - bestimmt nicht schön - so kann ich es halt !

Code: Alles auswählen

adressbuch = [['Muster Max', 'Musterstrasse 1', 'Musterhausen 1000',
               '012345678','02345677', 'max-muster@max.de', 'muster'],
              ['Muster Maxi', ' Mustergasse 1', 'Musterhausen 2000',
               '021234567', '028765432', 'maxi-muster@max.de', 'muster']]


for eintrag in range (len(adressbuch)):
    for feldname in range(len(FELDNAMEN)):
        print FELDNAMEN[feldname], adressbuch[eintrag][feldname]
Bei meinem ersten Ansatz ...? Das mit dem len würde ja nicht gehen ?

Code: Alles auswählen

adressbuch = {'Muster Max':['Musterstrasse 1', 'Musterhausen 1000',
                             '0123456789', '087654321', 'email:',
                             'max-muster@max.de', 'Bemerkung:', 'muster']}

#for eintrag in range (len(adressbuch)):
    #for feldname in range(len(FELDNAMEN)):
        #print FELDNAMEN[feldname], adressbuch[key[eintrag]][feldname]
geht narürlich nicht !
Da wären meine Probleme wieder !

Einträge über Indizes ansprechen - mh - also nicht über die Zahlenwerte !? Warum nicht ? Eine Funktion die alle Einträge über die Namen zusammensammelt - mh - alle Namen? - alle Orte? - was habe ich davon?

gruss und dank frank
BlackJack

Freitag 20. April 2007, 10:25

Wenn Du aus Fehlern lernen willst, solltest Du wissen was die Fehler waren. Erkläre mal was hierbei herauskommt und *warum*:

Code: Alles auswählen

print adressbuch[0], [1] # ergibt keine sinnvolle Ausgabe
Und bitte, bitte hör mit diesem ``range(len(liste))`` auf. Das wurde Dir jetzt schon mehrfach gesagt. Die Namen `eintrag` und `feldname` sind in dem Quelltext für die "Listen von Listen" irreführend weil es Indexe und keine Einträge oder Namen sind. Hier würden sie passen:

Code: Alles auswählen

for eintrag in adressbuch:
    for feldname, feld_wert in zip(FELDNAMEN, eintrag):
        print feldname, feld_wert
Ein Dictionary enthält Schlüssel und Werte und man kann über diese Paare mit den entsprechenden Methoden, wie `items()` was eine Liste erzeugt, oder `iteritems()` was einen Iterator über die Elemente zurückgibt, in einer Schleife iterieren und sie darin ausgeben. Oder `keys()`, `iterkeys()`, `values()` oder `itervalues()` für Schlüssel oder Werte.

Im Dictionary-Versuch sind zu viele Daten im Wert. Da haben sich Feldbezeichnungen eingeschlichen. Und man sollte den Namen mit in den Wert einfügen, sonst muss man ihn bei der Ausgabe gesondert behandeln.

Code: Alles auswählen

adressbuch = {'Muster Max':['Muster Max', 'Musterstrasse 1',
                            'Musterhausen 1000', '0123456789', '087654321',
                            'max-muster@max.de', 'muster']}

for name, felder in adressbuch.iteritems():
    for feldname, feld_wert in zip(FELDNAMEN, felder):
        print feldname, feld_wert
Ich denke aber nicht das ein Dictionary hier die richtige Datenstruktur ist, weil man selten exakt den kompletten Namen sucht. Für andere Suchen muss man dann trotzdem wieder linear alle Einträge durchgehen. Und Dictionaries sind ungeordnet, Adressen sortiert man aber ganz gerne.
EyDu
User
Beiträge: 4871
Registriert: Donnerstag 20. Juli 2006, 23:06
Wohnort: Berlin

Freitag 20. April 2007, 19:50

BlackJack hat geschrieben:Ich denke aber nicht das ein Dictionary hier die richtige Datenstruktur ist, weil man selten exakt den kompletten Namen sucht. Für andere Suchen muss man dann trotzdem wieder linear alle Einträge durchgehen. Und Dictionaries sind ungeordnet, Adressen sortiert man aber ganz gerne.
Am einfachsten ist es wahrscheinlich alles in eine SQLite-DB zu prügeln, aber die Aufgabe sieht doch eher nach einer Übung aus, als nach einem konkreten Projekt. Daher kann man sich ja auch langsam an eine schöne Lösung ranarbeiten.
Benutzeravatar
kaytec
User
Beiträge: 544
Registriert: Dienstag 13. Februar 2007, 21:57

Freitag 20. April 2007, 23:14

Dank BlackJack !

Warst ja mal wieder hart aber gerecht mit mir !

Es gibt für mich keine sinnvolle Ausgabe - für Python schon - gab ja keine Fehlermeldung. Eigentlich habe ich print [1] geschrieben und das ist ja auch passiert. So was evt.: schreibe Liste mit dem Element 1 ?

Das mit range(len(liste)) kann ich ja lassen - warum darf man Dinge nicht, die das gleiche machen. Macht für mich erst mal kein Sinn?!.

So was darf man schreiben: for i in range (len(liste)) ? Weil i für index steht und ich nicht auf die Elemente der Liste zugreife, sondern auf die Indexe der Element in der Liste.

for eintrag in adressbuch ist ok, weil ich nicht auf die indexe, sondern auf die wirklichen Einträge zugreife - auf die Elemnete der Liste (Der Ausdruck Element stimmt hoffentlich - steht so in meinem Buch)

Das mit den Dictionarys habe ich mal so verstanden: Eigentlich gelange ich nur über den Schlüssel an den gesamten Datensatz und nicht an die einzelnen Elemente. Das kann man nur über einen Zeiger(Iterator). Dieser zeigt mir im Speicher(ich nehme mal an Arbeitsspeicher) auf die Adresse wo es ja schon steht, da die Dictionary schon in den Speicher geladen wurde. ? Das wird völliger Quatsch sein :?


gruss und dank frank
BlackJack

Freitag 20. April 2007, 23:25

kaytec hat geschrieben:Es gibt für mich keine sinnvolle Ausgabe - für Python schon - gab ja keine Fehlermeldung. Eigentlich habe ich print [1] geschrieben und das ist ja auch passiert. So was evt.: schreibe Liste mit dem Element 1 ?
Das ist das was nach dem Komma stand.
Das mit range(len(liste)) kann ich ja lassen - warum darf man Dinge nicht, die das gleiche machen. Macht für mich erst mal kein Sinn?!.

So was darf man schreiben: for i in range (len(liste)) ? Weil i für index steht und ich nicht auf die Elemente der Liste zugreife, sondern auf die Indexe der Element in der Liste.
Aber da verwendest Du doch auch wieder ``range(len(liste))``. Ob die Schleifenvariable nun `i` oder anders heisst, ändert ja nichts daran das es umständlich und indirekt ist. Zumal `range()` eine Liste mit Zahlen erzeugt, also Speicherplatz belegt.
Benutzeravatar
kaytec
User
Beiträge: 544
Registriert: Dienstag 13. Februar 2007, 21:57

Freitag 20. April 2007, 23:30

Das war schnell !

Danke dir BlackJack!

Ich meinte nur den Namen der Variable I ist ok aber nicht eintrag. Das sowas viele Speicherplatz braucht - habe ich nicht gewusst. Das macht es mir dann schon verständlich. Falls ich mal python verstehe, gibt es Abeitsspeicher ausreichend :lol:

gruss und dank frank
EyDu
User
Beiträge: 4871
Registriert: Donnerstag 20. Juli 2006, 23:06
Wohnort: Berlin

Samstag 21. April 2007, 09:42

kaytec hat geschrieben:Ich meinte nur den Namen der Variable I ist ok aber nicht eintrag. Das sowas viele Speicherplatz braucht - habe ich nicht gewusst. Das macht es mir dann schon verständlich. Falls ich mal python verstehe, gibt es Abeitsspeicher ausreichend :lol:
Ganz verstanden hast du das Problem immer noch nicht. Es geht hier nicht um den Vebrauch des Arbeitsspeichers, sondern darum, dass du den Zugriff auf Elemente über Indizes versteckts:

Code: Alles auswählen

for index in range(len(liste)):
    print liste[index]
Hier machst du nichts anderes als über jedes Element der Liste zu laufen, welches man aber nicht sofort erkennen kann.

Der folgende Code tut genau das Gleiche (so lange du nicht Elemente in der Liste ersetzen willst), jedoch ist hier der Zugriff auf jedes Element direkt zu erkennen:

Code: Alles auswählen

for element in liste:
    print element
Wenn du tatsächlich mal zu dem Element noch den Index benötigst, dann kannst du "enumerate"-Built-In-Funktion verwenden:

Code: Alles auswählen

for index, element in enumerate(liste):
    print element #Richtig
    print liste[index] #Ganz böse
    liste[index] = 42 # Ok
Benutzeravatar
kaytec
User
Beiträge: 544
Registriert: Dienstag 13. Februar 2007, 21:57

Samstag 21. April 2007, 09:46

Hallo BlackJack !!!

Ich bin ja ein guter Lehrling und habe mir Deine Version mal angeschaut.

Code: Alles auswählen

if __name__ == '__main__':
    main()
Wenn der Name main ist, dann rufe Funktion main() auf ? Ich sehe da nicht den Bezug auf die Funktionen - macht es aber trotzdem ?

In main wird die Eingabe auf den passenden key getestet und falls dieser nicht vorhanden ist, gibt es den KeyError. Falls er vorhanden ist, wird der Aufruf der Funktion "zusammengebaut". Bei Eingabe 'B' wird noch abgespeichert und die Schleife wird durch break beendet. was ich nicht verstehe - warum passiert nicht wieder:

Code: Alles auswählen

if __name__ == '__main__':
    main()
Das laden() habe ich nicht ganz verstanden ! Es funktioniert so ungefähr wie meine Version - nur irgendwie schöner. Da werden Zeilennummern gebildet und verglichen mit der Länge der Feldnamen. % hat irgendwas mit modulo zu tun. Falls beim Vergleich 0 herauskommt (Nur der Fall bei vorhandenen Einträgen, da sonst keine Zeilennummer vorhanden) werden die Einträge eingefügt.

Nur irgendwie war da ein Fehler,denn auch bei keinen Einträgen wurde dies ausgeführt:

Code: Alles auswählen

adressbuch.append(''.join(eintrag))
Das hat dann aber einen Eintrag erzeugt [' '] und der wurde angezeigt und mitgezählt.

Habe es mal so geändert und bekomme bestimmt böse Schimpfe von BlackJack:

Code: Alles auswählen

 adressbuch.append(''.join(eintrag))
    if adressbuch ==['']:
        adressbuch=list()
So - gehe jetzt arbeiten !

gruss und dank frank
Benutzeravatar
kaytec
User
Beiträge: 544
Registriert: Dienstag 13. Februar 2007, 21:57

Samstag 21. April 2007, 20:19

Habe noch die Möglichkeit des Löschen und Editieren eingefügt!

Code: Alles auswählen

def ausgabe(adressbuch, schlusstext='im Adressbuch'):
    for eintrag in adressbuch:
        print '____________________________________'
        print
        print eintrag
        print '===================================='
        auswahl = raw_input('(E)ditieren o. (L)oeschen ?').upper()
        if auswahl == 'L':
            adressbuch.remove(eintrag)   
        elif auswahl =='E':
            adressbuch.remove(eintrag)
            eintragen(adressbuch)  

gruss frank
Benutzeravatar
kaytec
User
Beiträge: 544
Registriert: Dienstag 13. Februar 2007, 21:57

Samstag 21. April 2007, 20:31

In der Funktion laden() könnte man doch das sort() löschen, da es doch bei der Funktion eintragen() gemacht wird. Das Adressbuch öffne ich ja das erste Mal ohne Inhalt. Beim ersten Eintragen wirde es dann eh sortiert.

gruss frank
BlackJack

Samstag 21. April 2007, 23:07

Nachdem eine aufgerufene Funktion beendet ist, wird das Programm an der Stelle fortgesetzt die hinter dem Aufruf steht also nach dem ``main()``.

Modulo bildet den Rest einer Division, es wird also getestet ob die Zeilennummer ohne Rest durch die Anzahl der Felder im Datensatz teilbar ist.

Den Fehler mit dem letzten Datensatz könnte man auch lösen indem man prüft, ob `eintrag` etwas enthält bevor man es dem Adressbuch hinzufügt.

Code: Alles auswählen

if eintrag:
    adressbuch.append(''.join(eintrag))
Löschen und editieren haben das Problem, dass sie die Liste verändern über die iteriert wird. Das funktioniert nicht richtig, weil der aktuelle Eintrag gelöscht wird, alle nachfolgenden um eins nach vorne rücken um in nächsten Schleifendurchlauf dann nicht der nächste, sondern der übernächste Eintrag genommen wird. Oder es gibt eine Ausnahme falls man am Ende der Liste war.

Ich würde nach dem laden sortieren, weil man bei solchen Klartextformaten damit rechnen muss, dass jemand ausserhalb des Programms, z.B. mit einem Texteditor an den Daten gearbeitet hat.
Benutzeravatar
kaytec
User
Beiträge: 544
Registriert: Dienstag 13. Februar 2007, 21:57

Sonntag 22. April 2007, 22:20

Habe es mit dem Editieren und Löschen mal so geändert

Code: Alles auswählen

def ausgabe(adressbuch, schlusstext='im Adressbuch'):

    eintrag_loeschen = list()
    for eintrag in adressbuch:
        print '____________________________________'
        print
        print eintrag
        print '===================================='
        auswahl = raw_input('(E)ditieren o. (L)oeschen ?').upper()
        if auswahl == 'L':
            eintrag_loeschen = eintrag
        elif auswahl =='E':
            eintragen(adressbuch)
            adressbuch.remove(eintrag)
    if eintrag_loeschen:
        for eintrag in adressbuch:
            if eintrag == eintrag_loeschen:
                adressbuch.remove(eintrag)
    anzahl = len(adressbuch)
    if anzahl == 1:
        eintrags_text = 'Eintrag'
    else:
        eintrags_text = 'Eintraege'
    print 
    print anzahl, eintrags_text, schlusstext
    print

kann jetzt aber nur einen eintrag löschen - mh ?

gruss und dank frank
Benutzeravatar
kaytec
User
Beiträge: 544
Registriert: Dienstag 13. Februar 2007, 21:57

Sonntag 22. April 2007, 23:03

Habe es mal so versucht - geht aber nicht ?

Code: Alles auswählen

        if auswahl == 'L':
            loeschen += eintrag
        elif auswahl =='E':
            eintragen(adressbuch)
            adressbuch.remove(eintrag)
            
    if loeschen:
        for eintrag_loeschen in loeschen:
            for eintrag in adressbuch:
                if eintrag == eintrag_loeschen:
                    adressbuch.remove(eintrag)
gruss und dank frank
BlackJack

Sonntag 22. April 2007, 23:21

Die Idee ist ja schon richtig, Du müsstest Dir aber nochmal die Methoden und Operatoren auf Listen anschauen.

Und das "richtige" Löschen der Einträge ist wieder mal viel zu kompliziert. Der erste Test ist überflüssig. Wenn kein Eintrag in der Liste `loeschen` vorhanden ist, dann wird die ``for``-Schleife nicht durchlaufen, das muss man nicht vorher testen.

Und die `remove()`-Methode sucht und entfernt das übergebene Objekt in der Liste. Da ist also eine Schleife die nichts vollbringt, ausser unnötig Rechenzeit zu verbrauchen.
Antworten