Seite 1 von 1

[Anfänger] Mehrdimensionales Array

Verfasst: Freitag 29. März 2013, 20:33
von alonzo
Hallo zusammen

ich wollte mich über die Ostertage etwas mit Python befassen und beschäftige mich fleissig mit dem Tutorial 'Learn Python The Hard Way'.
So weit ist dort vieles sehr gut Erklärt. Nun wollte ich mich eigenständig an einem Adressbuch versuchen und scheitere schon am deklarieren der Variablen.

Datenmodell

Referenznummer :: Name
Referenznummer :: Vorname
usw.

Hier mein erster Gehversuch mit einer verschachtelten Liste

Code: Alles auswählen

>>> adressbuch= {}
>>> adressbuch['1']['name'] = "alonzo"
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
KeyError: '1'
Der zweite mit einem array

Code: Alles auswählen

>>> adressbuch = []
>>> adressbuch[1]['name'] = "alonzo"
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
IndexError: list index out of range
dritter versuch

Code: Alles auswählen

>>> ref = 1234
>>> adressbuch[ref] = {}
>>> adressbuch[ref]['name'] = "alonzo"
>>> print adressbuch[ref]['name']
alonzo
Sprich mein 3ter Versuch war Erfolgreich und ich bin halbwegs happy. Bin ich hier auf dem richtigen Weg oder gibt es noch eine Empfehlens wertere Methode?

Re: [Anfänger] Mehrdimensionales Array

Verfasst: Freitag 29. März 2013, 20:54
von cofi
Zuerst: 1 und 3 benutzen Dictionaries, keine Listen, und 2 benutzt eine Liste, kein Array.

Dein Problem ist, dass du nichts benutzen kannst, das du noch nicht erstellt hast. Darum funktioniert 1 nicht, aber 3.

Mit collections.defaultdict funktioniert dann auch 1:

Code: Alles auswählen

from collections import defaultdict
adressbuch = defaultdict(dict)
adressbuch['1']['name'] = 'alonzo'
Das Problem hierbei ist aber, dass du keinen sinnvollen Key fuer den Zugriff hast (oder zumindest keinen den du sinnvoll benutzen wirst).
Hier ist 2 sinnvoller:

Code: Alles auswählen

adressbuch = []
adressbuch.append({'name': 'alonzo', ....})

Re: [Anfänger] Mehrdimensionales Array

Verfasst: Freitag 29. März 2013, 21:28
von diesch
Es ist vermutlich sinnvoller, wenn du für die Adressen eine eigene Klasse definierst, z.B.:

Code: Alles auswählen

class Adresse:
    def __init__(self, vorname=None, name=None):
        self.vorname = vorname
        self.name = name
Dann kannst du Instanzen dieser Klasse z.B. in einem dict speichern:

Code: Alles auswählen

adressbuch= {}

adressbuch[1234] = Adresse(name='alonzo')
adressbuch[456] = Adresse(vorname='John', name='Doe')

Re: [Anfänger] Mehrdimensionales Array

Verfasst: Samstag 30. März 2013, 03:01
von Hyperion
diesch hat geschrieben:Es ist vermutlich sinnvoller, wenn du für die Adressen eine eigene Klasse definierst, z.B.:
Das kann man natürlich machen, aber man muss es nicht. Der OP sagt ja gerade, dass er erst *lernt* - da wird er mit Klassen und tieferer OOP vermutlich noch wenig anfangen können.

Man kann zu Beginn gut und gerne mit den Basisdatenstrukturen arbeiten; immerhin ist es ja wohl auch das Ziel, diese zu verinnerlichen und zu verstehen.

Da die Objekte eines solchen Adressbuches - wie von DIr gezeigt - keinen inneren Zustand aufweisen, sehe ich darin keinen Mehrwert.

Re: [Anfänger] Mehrdimensionales Array

Verfasst: Samstag 30. März 2013, 09:40
von alonzo
Danke für eure Unterstützung.

Bei der Verwendung von Klassen bin ich noch nicht angekommen.
Cofi hat es mir gut verdeutlicht, dass ich den Unterschied von einem dict / list noch nicht ganz verstanden habe.

Bisher habe ich vorausgesetzt, dass man Datentypen nicht explizit initialisieren muss. Wie sich zeigt - weit gefehlt. Ich fange noch mal von vorne an was Datenstrukturen angeht und mache das Tutorial bis zum Schluss durch. Mein erster Selbstversuch verdeutlicht das es nötig ist und ich zu enthusiastisch war

Re: [Anfänger] Mehrdimensionales Array

Verfasst: Samstag 30. März 2013, 10:08
von Hyperion
alonzo hat geschrieben: Bisher habe ich vorausgesetzt, dass man Datentypen nicht explizit initialisieren muss. Wie sich zeigt - weit gefehlt.
Du musst in Python nichts *deklarieren* (im Gegensatz zu vielen statisch typisierten Sprachen), aber natürlich musst Du Objekte *erzeugen*!

Ich weiß nicht, ob das aus cofis Post deutlich geworden ist, aber ``collections.defaultdict`` zaubert auch nichts aus dem Hut, sondern dürfte intern analog zu diesem Beispiel mit herkömmlichem Dictionary funktionieren:

Code: Alles auswählen

# wir erzeugen das top level Dictionary
adressbuch = dict()
# wir prüfen, ob noch kein Eintrag für einen gegebeben Schlüssel
# existiert und implizieren damit, dass wir das *innere* Dictionary
# neu anlegen müssen
if "1" not in adressbuch.keys():
    # wir erzeugen ein inneres Dictionary
    adressbuch["1"] = dict()
# wir können nun hier problemlos Key-Value-Paare im *inneren*
# Dictionary setzen, da wir sicher sind, dass dieses existiert.
adressbuch["1"]["name"] = "alonzo"
#--top level---|---inneres dict---
(``defaultdict`` sieht ja stark nach Decorator-Pattern aus - sollte ich mir mal im Quellcode angucken :-) )

Wenn man nur das äußere Dictionary anlegt, dann muss man natürlich ganz normal Einträge vornehmen und Key-Value-Paare anlegen. Der Value-Part besteht hier eben wieder aus einem Dictionary, welches die Adressdetails beinhaltet. Das kann aber jedes beliebige Python-Objekt sein! (Also auch Funktionen, Lambdas, usw.) Natürlich muss man dieses Objekte erzeugen, wenn man sie braucht. ``defaultdict`` macht da nichts anderes, was man nicht auch "zu Fuß" umsetzen kann.

Ich denke schon, dass Du Dir selber auch Beispiele zum Thema Datenstrukturen ausdenken solltest. Natürlich schadet es nicht, Dir noch einmal die Basics anzugucken, aber Du musst das ja auch üben. Und das passiert nur durchs Ausprobieren :-)

Re: [Anfänger] Mehrdimensionales Array

Verfasst: Samstag 30. März 2013, 11:01
von snafu
alonzo hat geschrieben:Bisher habe ich vorausgesetzt, dass man Datentypen nicht explizit initialisieren muss. Wie sich zeigt - weit gefehlt.
Naja, das Problem bei `adressbuch['1']['name']` (wenn `adressbuch` vom Typ `dict` ist) ist folgendes: Es wird zwar der Schlüssel `1` problemlos überschrieben oder automatisch erstellt, sobald man eine Zuweisung für den Schlüsselnamen macht, jedoch bezieht sich das zweite eckige Klammernpaar ja auf den Wert, der *hinter* dem Schlüssel mit der `1` steckt. Du nimmst zwar an, dass es sich bei diesem Wert wiederum um etwas vom Typ `dict` handelt, aber Python kann dies nicht wissen. Dafür müsste der Typ so definiert sein, dass er automatisch ein leeres `dict` anlegt, sobald eine Zuweisung auf einen bisher nicht benutzten Schlüssel stattfindet. Dies wird aber nicht gemacht und daher wirft Python dir den Fehler.

Und bei Listen ist es so, dass diese bei ihrer Initialisierung eine Größe haben, die der Anzahl der an sie übergebenen Elemente entspricht. Zum Beispiel würde `meine_liste = ['foo', 'bar', 'baz']` zur Erstellung einer Liste mit 3 Elementen und den dadurch zulässigen Indexwerten 0, 1 und 2 führen. Wenn dein Adressbuch mit einer leeren Liste beginnt (`adressbuch = []`, Größe also 0), dann müssen neue Elemente stets mittels `adressbuch.append(element)` angefügt werde. Listen sind eben von ihrer Idee her etwas anderes als Arrays. Es werden dabei keine Zuweisungen für beliebige unbekannte Indizes (z.B. `adressbuch[1] = adresse` bei leerem Adressbuch) unterstützt. Das sollte einem schon klar sein...