Python Dictionaries (dict + frozendict) (C) 2020-2026 T.Birnthaler OSTC GmbH
=======================================
Doku --> docs.python.org/3/library/stdtypes.html#dict
--> docs.python.org/3/library/stdtypes.html#frozendict
Dictionaries (dict, frozendict) (auch Map, Hash, Assoziatives Array, Zuordnung,
Verzeichnis) speichern PAARE/ITEMS aus KEY + VALUE und damit eine "Beziehung"
zwischen zwei Datenwerten (nur Beziehung in Richtung KEY --> VALUE).
Ein Dictionary entspricht einer 2-spaltigen Datenbank-Tabelle mit festen
Spaltennamen KEY + VALUE und enthält als Datensätze KEY-VALUE-PAARE. Die Spalte
KEY ist UNIQUE und INDIZIERT, d.h. der Zugriff über diese Spalte ist unabhängig
von der Anzahl der Datensätze + sehr schnell. Die Spalte VALUE ist NON-UNIQUE
und nicht INDIZIERT, d.h. der Zugriff über diese Spalte ist abhängig von der
Anzahl der Datensätze + relativ langsam.
Das Dictionary liegt im Speicher und "stirbt" am Ende des Programmes, daher ist
es NICHT PERSISTENT, es gibt nur einen Zugriffspfad (keine MULTI-USER
Fähigkeit) und Zugriffe darauf sind WESENTLICH SCHNELLER als auf echte
Datenbanken (keine SQL-Statements erzeugen, versenden, parsen und beantworten,
keine NW-Verbindung, kein Protokoll-Overhead, keine Plattenzugriffe, ...).
Die Datensätze sind UN-GEORDNET (seit Python 3.7 bleibt die Einfüge-Reihenfolge
erhalten) und UN-NUMERIERT. Die DATENTYPEN der beiden Spalten sind nicht
festgelegt und können daher beliebig gemischt sein. Im KEY können aber nur
IM-MUTABLE Datentypen (besser HASHABLE) Datentypen gespeichert werden, im VALUE
sind alle Python-Datentypen erlaubt. Die Spalte VALUE kann per
CONTAINER-Datentyp tuple, list, set, dict, ... auch MEHRSPALTIG und sogar
HIERARCHISCH sein.
d1 = {} oder d1 = dict() # Leeres Dictionary
d2 = {"abc": 123, True: 4.0, (1,2,3): None} # 3 Paare/Items
d3 = {"a": 1, "b": 2, "c": 1, "d": 3} # 4 Paare/Items
d4 = dict(a=1, b=2, c=1, d=3) # Alternative Schreibweise
d5 = dict([("a",1), ("b",2), ("c",1), ("d",3)]) # Alternative Schreibweise
* KEYS müssen IM-MUTABLE Objekte bzw. eigentlich HASHABLE Objekte sein
(NoneType, bool, int, float, complex, str, tuple, frozenset, bytes).
* KEYS sind UNIQUE (d.h. der gleiche Key kann nur 1x vorkommen).
* Als VALUE sind beliebige PYTHON-OBJEKTE erlaubt.
* VALUES dürfen NON-UNIQUE sein (d.h. der gleiche Value darf mehrfach vorkommen).
* Dictionaries sind bezüglich KEY/VALUE UN-GEORDNET (seit Python 3.7 bleibt die
Einfüge-Reihenfolge erhalten). Will man Zugriff in spezieller Reihenfolge,
muss man beim Zugriff MANUELL sortieren.
* Die ZUGRIFFSGESCHWINDIGKEIT auf einen bestimmten KEY (und damit seinen VALUE)
ist UN-ABHÄNGIG von der Dictionary-Größe immer gleich SCHNELL (RANDOM ACCESS).
* Die ZUGRIFFSGESCHWINDIGKEIT auf einen bestimmten VALUE ist ABHÄNGIG von der
Dictionary-Größe und immer LANGSAM (da sie das Durchsuchen des gesamten
Dictionarys erfordert).
Folgende Operation werden von dict und frozendict unterstützt (K ist ein Key =
im-mutable Objekt, V und DFLT sind Values = beliebige Objekte, D, D2 und E sind
Dictionaries, ITBL ist ein Iterable, L ist eine Liste):
ACHTUNG: Nur LESENDE Operationen, das Dictionary D bleibt UNVERÄNDERT!
+------------------------+-----------------------------------------------------+
| for K in D: ... | Alle Keys K von D durchlaufen (ungeordnet) |
| for K in D.keys(): ... | Alle Keys K von D durchlaufen (ungeordnet) |
| for V in D.values(): | Alle Values V von D durchlaufen (ungeordnet) |
| for (K,V) in D.items() | Alle Keys+Values K+V von D durchlaufen (ungeordnet) |
+------------------------+-----------------------------------------------------+
| D == D2 | Dictionaries gleich (alle Key-Value Paare)? |
| D != D2 | Dictionaries un-gleich (ein Key oder Value)? |
+------------------------+-----------------------------------------------------+
| K in D | Key K in D enthalten? |
| K not in D | Key K in D nicht enthalten? |
+------------------------+-----------------------------------------------------+
| len(D) | Anzahl Keys/Values/Paare/Items |
+------------------------+-----------------------------------------------------+
| V = D[K] | Value von Key K holen (KeyError falls Key fehlt) |
| V = D.get(K, DFLT) | Value von Key K holen (oder DFLT, kein KeyError) |
+------------------------+-----------------------------------------------------+
| L = D.keys() | Liste aller Keys (ungeordnet) |
| L = D.values() | Liste aller Values (ungeordnet) |
| L = D.items() | Liste aller (Key,Value)-Paare/Items (ungeordnet) |
+------------------------+-----------------------------------------------------+
| L = list(D) | Abkürzung für D.keys() |
| L = iter(D) | Abkürzung für iter(D.keys()) |
| L = reversed(D) | Abkürzung für reversed(D.keys()) | PY3.8
+------------------------+-----------------------------------------------------+
| D2 = D.copy() | Shallow/Flache Kopie |
+------------------------+-----------------------------------------------------+
| E = D | D2 | D2 zu D hinzufüg, D2-Val überschreibt D bei gl. Key | PY3.9
+------------------------+-----------------------------------------------------+
ACHTUNG: SCHREIBENDE Operationen sind nur für dict möglich (nicht frozendict)
das Dictionary D wird VERÄNDERT (bleibt aber das gleiche Objekt)!
ACHTUNG: Die Operation |= ist auch auf frozendict anwendbar,
erzeugen aber einen NEUEN frozendict!
+-----------------------+------------------------------------------------------+
| D[K] = V | Value V für vorhandenen Key K (er)setzen |
| | Key K mit Value V hinzufügen (falls NICHT vorhand.) |
| D.setdefault(K, DFLT) | Value zu Key K auf DFLT setzen (falls NICHT vorhand.)|
| | + Value von Key zurückgeben |
+-----------------------+------------------------------------------------------+
| del D[K] | Key K + Value löschen (oder KeyError falls Key fehlt)|
| V = D.pop(K, DFLT) | Value V von Key K holen (KeyError/DFLT) + Key löschen|
| (K,V) = D.popitem() | Paar/Item (K,V) holen + entf. (KeyError falls D leer)|
+-----------------------+------------------------------------------------------+
| D = dict.fromkeys(I) | Dict D mit Keys aus Iterable I + Wert None erzeugen |
| D = dict.fromkeys(I,V)| Dict D mit Keys aus Iterable I + Wert V erzeugen |
| D.update(D2|ITER) | D2/ITER zu D hinzufügen (überschreibt D bei gl. Key) |
| D.clear() | Dict D leeren (alle Keys + Values entfernen) |
+-----------------------+------------------------------------------------------+
| D |= D2 | D2 zu D hinzufügen, D2-Val überschreibt D bei gl. Key| PY3.9
+-----------------------+------------------------------------------------------+
ITER = Iterable mit PAAREN als Elemente (z.B. Liste von 2-er Tupeln)
HINWEIS: Zugriff auf ein Dictionary mit einem NICHT vorhandenen Key
löst die Exception "KeyError" aus.
HINWEIS: Bei Funktion "fromkeys" muss "dict." als Präfix verwendet werden, da
noch kein Dictionary-Objekt vorhanden ist, auf das "fromkeys" angewendet werden
kann (sondern durch "fromkeys" erst erzeugt wird).
HINWEIS: Seit Python 3.7 entspricht die Key-Reihenfolge im Dictionary der
EINFÜGE-REIHENFOLGE und bleibt bei Operationen auf dem Dictionary erhalten.
Vorher war die Reihenfolge der Keys ZUFÄLLIG und konnte sich jederzeit ändern.
HINWEIS: Die Keys "True/False" in Dictionaries werden mit den Keys 1/0 (int),
1.0/0.0 (float) und 1+0j/0+0j (complex) IDENTIFIZIERT, da sie den gleichen
HASH-Wert haben (d.h. jeder der folgenden Keys kann nur 1x in einem Dictionary
vorkommen):
True <--> 1 <--> 1.0 <--> 1+0j <--> 1+0.0j <--> 1.0+0j <--> 1.0+0.0j
False <--> 0 <--> 0.0 <--> 0+0j <--> 0+0.0j <--> 0.0+0j <--> 0.0+0.0j
Vor PY3.7 war das ein ZUFÄLLIGER Key + Wert, seit PY3.7 ist es der ERSTE im
Dictionary vorkommende Key mit dem LETZTEN diesem Key zugeordneten Wert:
D = {True: "bool", 1: "int", 1.0: "float", 1+0j: "complex"} # --> {True: 'complex'}
D = {1: "int", True: "bool", 1.0: "float", 1+0j: "complex"} # --> {1: 'complex'}
D = {0+0j: "complex", 0: "int", False: "bool", 0.0: "float"} # --> {0+0j: 'float'}
D = {0.0: "float", 0+0j: "complex", 0: "int", False: "bool"} # --> {0.0: 'bool'}