In Python ist eine Sammlung ein Objekt, das eine Gruppe von Elementen enthÀlt und es ermöglicht, mit ihnen als Einheit zu arbeiten.
Sammlungen unterstĂŒtzen typischerweise:
- Iteration (
for element in sammlung) - MitgliedschaftsprĂŒfung (
x in sammlung) - LĂ€ngenbestimmung (
len(sammlung)) - Zugriff per Index oder SchlĂŒssel (wenn geordnet oder assoziativ)
Python hat keine strikte âSammlungs-Schnittstelleâ, folgt aber informellen Protokollen. Wenn ein Objekt
__iter__,__len__,__contains__implementiert, gilt es als Sammlung.
Was KEINE Sammlung ist
Folgende Typen sind keine Sammlungen, da sie keine Gruppen von Elementen enthalten:
int,float,boolâ SkalarwerteNoneâ Fehlen eines Werts- Funktionen, Module, Klassen â sind Objekte, aber keine Datencontainer (es sei denn, sie enthalten
__dict__)
Eingebaute Sammlungen
Ohne Import verfĂŒgbar:
| Typ | Beschreibung |
|---|---|
list | Geordnete, verÀnderbare Sequenz. |
tuple | Geordnete, unverÀnderbare Sequenz. |
dict | Geordnete SchlĂŒssel-Wert-Zuordnung (seit Python 3.7). |
set | Ungeordnete Sammlung eindeutiger Elemente. |
frozenset | UnverÀnderbare Version von set. |
Erweiterte Sammlungen aus der Standardbibliothek
| Typ | Modul | Zweck |
|---|---|---|
SimpleNamespace | types | Objekt mit dynamischen Attributen (Alternative zu dict mit Punktzugriff). |
namedtuple | collections | UnverÀnderbares Tupel mit benannten Feldern. |
deque | collections | Doppelseitige Warteschlange â effizient fĂŒr Operationen an beiden Enden. |
Counter | collections | Subklasse von dict zum ZĂ€hlen von Objekten. |
defaultdict | collections | Wörterbuch mit Standardwerten fĂŒr fehlende SchlĂŒssel. |
dataclass | dataclasses | Generiert automatisch __init__, __repr__, __eq__ usw. |
UserList | collections | Basisklasse fĂŒr benutzerdefinierte Listen. |
UserDict | collections | Basisklasse fĂŒr benutzerdefinierte WörterbĂŒcher. |
Andere sammlungsÀhnliche Typen
Obwohl nicht immer âSammlungenâ genannt, reprĂ€sentieren oder speichern diese Typen ebenfalls Datengruppen.
1. str â Zeichenkette
Geordnete, unverÀnderbare Sequenz von Zeichen.
s = "Python"
print(len(s)) # â 6
print(s[0]) # â P
print('y' in s) # â True
print(list(s)) # â ['P', 'y', 't', 'h', 'o', 'n']
2. bytes, bytearray
bytesâ unverĂ€nderbare Byte-Sequenz.bytearrayâ verĂ€nderbare Version.
b = b"hallo"
print(b[0]) # â 104
print(len(b)) # â 5
ba = bytearray(b"hallo")
ba[0] = 72
print(ba) # â bytearray(b'Hallo')
3. range
Faule, geordnete Zahlenfolge. Speichert Elemente nicht im Speicher.
r = range(3)
print(list(r)) # â [0, 1, 2]
print(1 in r) # â True
print(r[2]) # â 2
4. array.array
Speichert homogene numerische Daten kompakt (wie in C).
from array import array
arr = array('i', [1, 2, 3]) # 'i' = signed int
print(arr) # â array('i', [1, 2, 3])
5. Generatoren und Iteratoren
Speichern keine Daten â generieren sie bei Bedarf. UnterstĂŒtzen weder len() noch Indexierung.
gen = (x * 2 for x in range(3))
print(list(gen)) # â [0, 2, 4]
# len(gen) â TypeError
6. ChainMap (aus collections)
Gruppiert mehrere Dictionaries in einer einzigen Sicht â Suche durchlĂ€uft Maps in Reihenfolge.
from collections import ChainMap
d1 = {'a': 1}
d2 = {'b': 2}
cm = ChainMap(d1, d2)
print(cm['a']) # â 1
print(cm['b']) # â 2
7. OrderedDict (aus collections)
Dictionary, das EinfĂŒgereihenfolge beibehĂ€lt. Relevant fĂŒr Python < 3.7.
from collections import OrderedDict
od = OrderedDict([('a', 1), ('b', 2)])
print(od) # â OrderedDict([('a', 1), ('b', 2)])
8. enum.Enum, enum.Flag
Sammlungen benannter Konstanten.
from enum import Enum
class Farbe(Enum):
ROT = 1
GRUEN = 2
print(list(Farbe)) # â [<Farbe.ROT: 1>, <Farbe.GRUEN: 2>]
9. typing.NamedTuple, typing.TypedDict
Typisierte Wrapper um namedtuple und dict.
from typing import NamedTuple, TypedDict
class Person(NamedTuple):
name: str
alter: int
p = Person("Anna", 25)
class Film(TypedDict):
titel: str
jahr: int
m: Film = {"titel": "Matrix", "jahr": 1999}
10. heapq, bisect â Werkzeuge, keine Sammlungen
Arbeiten mit Sammlungen, sind aber keine:
heapqâ Heap-Warteschlange ĂŒber Listen.bisectâ hĂ€lt sortierte Reihenfolge in Listen.
1. Listen â list
Geordnete, verÀnderbare Sammlung. Elemente können sich wiederholen, beliebige Typen erlaubt.
Wird verwendet, wenn eine flexible Sequenz benötigt wird: HinzufĂŒgen, Entfernen, Ăndern von Elementen.
Erstellung: []
lukas_list = ["Lukas", "Berlin", 30, "Ingenieur"]
print(f"Listen-Erstellung: {lukas_list}")
# â Listen-Erstellung: ['Lukas', 'Berlin', 30, 'Ingenieur']
print(f"Element bei Index 0: {lukas_list[0]}")
# â Element bei Index 0: Lukas
lukas_list[2] = 31
print(f"Nach Ănderung: {lukas_list}")
# â Nach Ănderung: ['Lukas', 'Berlin', 31, 'Ingenieur']
lukas_list.append("verheiratet")
print(f"Nach append: {lukas_list}")
# â Nach append: ['Lukas', 'Berlin', 31, 'Ingenieur', 'verheiratet']
lukas_list.insert(1, "Deutschland")
print(f"Nach insert: {lukas_list}")
# â Nach insert: ['Lukas', 'Deutschland', 'Berlin', 31, 'Ingenieur', 'verheiratet']
lukas_list.remove("Ingenieur")
print(f"Nach remove (Wert): {lukas_list}")
# â Nach remove (Wert): ['Lukas', 'Deutschland', 'Berlin', 31, 'verheiratet']
del lukas_list[2]
print(f"Nach Löschung (Index): {lukas_list}")
# â Nach Löschung (Index): ['Lukas', 'Deutschland', 31, 'verheiratet']
lukas_list.extend(["Hobbys", "Angeln"])
print(f"Nach extend: {lukas_list}")
# â Nach extend: ['Lukas', 'Deutschland', 31, 'verheiratet', 'Hobbys', 'Angeln']
lukas_list.pop()
print(f"Nach pop: {lukas_list}")
# â Nach pop: ['Lukas', 'Deutschland', 31, 'verheiratet', 'Hobbys']
2. WörterbĂŒcher â dict
Sammlung von SchlĂŒssel â Wert-Paaren. SchlĂŒssel mĂŒssen hashbar sein. Seit Python 3.7 bleibt die EinfĂŒgereihenfolge erhalten.
NĂŒtzlich fĂŒr strukturierte Daten: Profile, Konfigurationen, JSON.
Erstellung: {}
anna_dict = {"name": "Anna", "alter": 25, "stadt": "MĂŒnchen", "beruf": "KĂŒnstlerin"}
print(f"Dict-Erstellung: {anna_dict}")
# â Dict-Erstellung: {'name': 'Anna', 'alter': 25, 'stadt': 'MĂŒnchen', 'beruf': 'KĂŒnstlerin'}
print(f"Wert fĂŒr SchlĂŒssel 'name': {anna_dict['name']}")
# â Wert fĂŒr SchlĂŒssel 'name': Anna
anna_dict["alter"] = 26
print(f"Nach Aktualisierung: {anna_dict}")
# â Nach Aktualisierung: {'name': 'Anna', 'alter': 26, 'stadt': 'MĂŒnchen', 'beruf': 'KĂŒnstlerin'}
anna_dict["hobby"] = "Malerei"
print(f"Nach HinzufĂŒgen: {anna_dict}")
# â Nach HinzufĂŒgen: {'name': 'Anna', 'alter': 26, 'stadt': 'MĂŒnchen', 'beruf': 'KĂŒnstlerin', 'hobby': 'Malerei'}
del anna_dict["stadt"]
print(f"Nach Löschung: {anna_dict}")
# â Nach Löschung: {'name': 'Anna', 'alter': 26, 'beruf': 'KĂŒnstlerin', 'hobby': 'Malerei'}
hobby = anna_dict.pop("hobby")
print(f"Nach pop: {anna_dict}, Wert: {hobby}")
# â Nach pop: {'name': 'Anna', 'alter': 26, 'beruf': 'KĂŒnstlerin'}, Wert: Malerei
print(f"SchlĂŒssel 'name' vorhanden: {'name' in anna_dict}")
# â SchlĂŒssel 'name' vorhanden: True
3. Tupel â tuple
Geordnete, unverĂ€nderbare Sammlung. Geeignet fĂŒr feste Daten.
Wird verwendet, wenn UnverĂ€nderlichkeit wichtig ist: Koordinaten, Parameter, RĂŒckgabewerte.
Erstellung: ()
lukas_tuple = ("Lukas", "Berlin", 30, "Ingenieur")
print(f"Tupel-Erstellung: {lukas_tuple}")
# â Tupel-Erstellung: ('Lukas', 'Berlin', 30, 'Ingenieur')
print(f"Element bei Index 2: {lukas_tuple[2]}")
# â Element bei Index 2: 30
# lukas_tuple[0] = "Max" â TypeError
# lukas_tuple.append("etwas") â AttributeError
- Tupel verbrauchen weniger Speicher und sind schneller als Listen.
- Ideal, wenn VerÀnderbarkeit nicht benötigt wird.
4. SimpleNamespace
Einfache Klasse aus types zur Erstellung von Objekten mit dynamischen Attributen. Zugriff per Punktnotation (obj.attr).
NĂŒtzlich, wenn man obj.name-Syntax ohne Klassendefinition möchte.
from types import SimpleNamespace
anna_ns = SimpleNamespace(name="Anna", alter=25, stadt="MĂŒnchen")
print(f"Objekt: {anna_ns}")
# â Objekt: namespace(name='Anna', alter=25, stadt='MĂŒnchen')
print(f"Name: {anna_ns.name}")
# â Name: Anna
anna_ns.alter = 26
print(f"Nach Ănderung: {anna_ns}")
# â Nach Ănderung: namespace(name='Anna', alter=26, stadt='MĂŒnchen')
anna_ns.beruf = "KĂŒnstlerin"
print(f"Mit neuem Attribut: {anna_ns}")
# â Mit neuem Attribut: namespace(name='Anna', alter=26, stadt='MĂŒnchen', beruf='KĂŒnstlerin')
del anna_ns.stadt
print(f"Nach Löschung: {anna_ns}")
# â Nach Löschung: namespace(name='Anna', alter=26, beruf='KĂŒnstlerin')
setattr(anna_ns, "hobby", "Malerei")
print(f"Via setattr: {anna_ns}")
# â Via setattr: namespace(name='Anna', alter=26, beruf='KĂŒnstlerin', hobby='Malerei')
delattr(anna_ns, "hobby")
print(f"Via delattr: {anna_ns}")
# â Via delattr: namespace(name='Anna', alter=26, beruf='KĂŒnstlerin')
- Alternative zu dict, wenn
obj.namegegenĂŒberobj['name']bevorzugt wird.
5. Mengen â set
Ungeordnete Sammlung eindeutiger Elemente. UnterstĂŒtzt Mengenoperationen: Vereinigung, Schnitt, Differenz.
Wird zur Duplikatentfernung und MitgliedschaftsprĂŒfung verwendet.
Erstellung: {} oder set()
zahlen = {1, 2, 3, 3, 2, 1}
print(f"Menge: {zahlen}")
# â Menge: {1, 2, 3}
zahlen.add(4)
print(f"Nach HinzufĂŒgen: {zahlen}")
# â Nach HinzufĂŒgen: {1, 2, 3, 4}
zahlen.remove(2)
print(f"Nach Entfernen: {zahlen}")
# â Nach Entfernen: {1, 3, 4}
andere = {3, 4, 5}
print(f"Vereinigung: {zahlen | andere}")
# â Vereinigung: {1, 3, 4, 5}
print(f"Schnitt: {zahlen & andere}")
# â Schnitt: {3, 4}
print(f"Differenz: {zahlen - andere}")
# â Differenz: {1}
6. UnverĂ€nderbare Mengen â frozenset
UnverĂ€nderbare Version von set. Kann als Dictionary-SchlĂŒssel oder Mengenelement verwendet werden.
frozen = frozenset([1, 2, 3, 2])
print(f"frozenset: {frozen}")
# â frozenset: frozenset({1, 2, 3})
andere = frozenset([3, 4])
print(f"Schnitt: {frozen & andere}")
# â Schnitt: frozenset({3})
print(f"Vereinigung: {frozen | andere}")
# â Vereinigung: frozenset({1, 2, 3, 4})
# frozen.add(5) â AttributeError
7. namedtuple â benannte Tupel
UnverÀnderbare Struktur mit Zugriff per Feldname. Lesbarer als normale Tupel.
from collections import namedtuple
Person = namedtuple("Person", ["name", "alter", "stadt"])
anna = Person("Anna", 25, "MĂŒnchen")
print(f"Objekt: {anna}")
# â Objekt: Person(name='Anna', alter=25, stadt='MĂŒnchen')
print(f"Name: {anna.name}")
# â Name: Anna
print(f"Alter: {anna[1]}")
# â Alter: 25
# anna.alter = 26 â AttributeError
anna_neu = anna._replace(alter=26)
print(f"Kopie mit Ănderung: {anna_neu}")
# â Kopie mit Ănderung: Person(name='Anna', alter=26, stadt='MĂŒnchen')
- Ideal fĂŒr DatensĂ€tze: Punkte, Benutzer, Konfigurationen â wenn UnverĂ€nderlichkeit und Lesbarkeit zĂ€hlen.
8. deque â doppelseitige Warteschlange
Optimiert fĂŒr schnelle Operationen an beiden Enden. Effizienter als list fĂŒr appendleft, popleft.
from collections import deque
d = deque([1, 2, 3])
print(f"Initiale deque: {d}")
# â Initiale deque: deque([1, 2, 3])
d.appendleft(0)
print(f"Nach appendleft: {d}")
# â Nach appendleft: deque([0, 1, 2, 3])
d.append(4)
print(f"Nach append: {d}")
# â Nach append: deque([0, 1, 2, 3, 4])
links = d.popleft()
print(f"Nach popleft: {links}, verbleibend: {d}")
# â Nach popleft: 0, verbleibend: deque([1, 2, 3, 4])
rechts = d.pop()
print(f"Nach pop: {rechts}, verbleibend: {d}")
# â Nach pop: 4, verbleibend: deque([1, 2, 3])
- Wird in Algorithmen verwendet: BFS, LRU-Caches, Puffer â wenn Endoperationen schnell sein mĂŒssen.
9. Counter â ElementzĂ€hler
ZĂ€hlt die HĂ€ufigkeit von Elementen in einem iterierbaren Objekt. NĂŒtzlich fĂŒr Statistiken und Analysen.
from collections import Counter
text = "abracadabra"
c = Counter(text)
print(f"Buchstaben-ZĂ€hlung: {c}")
# â Buchstaben-ZĂ€hlung: Counter({'a': 5, 'b': 2, 'r': 2, 'c': 1, 'd': 1})
print(f"HĂ€ufigkeit von 'a': {c['a']}")
# â HĂ€ufigkeit von 'a': 5
print(f"Top 3: {c.most_common(3)}")
# â Top 3: [('a', 5), ('b', 2), ('r', 2)]
c2 = Counter("bukva")
c.update(c2)
print(f"Nach update: {c}")
# â Nach update: Counter({'a': 6, 'b': 3, 'r': 2, 'c': 1, 'd': 1, 'u': 1, 'k': 1, 'v': 1})
- NĂŒtzlich fĂŒr Textanalyse, Logs, Abstimmungen â ĂŒberall, wo âhĂ€ufigste Elementeâ zĂ€hlen.
10. defaultdict â Wörterbuch mit Standardwerten
Erzeugt automatisch Standardwerte fĂŒr fehlende SchlĂŒssel. Entfernt if key in dict-PrĂŒfungen.
from collections import defaultdict
dd_list = defaultdict(list)
dd_list["fruechte"].append("Apfel")
dd_list["fruechte"].append("Banane")
print(f"Liste: {dict(dd_list)}")
# â Liste: {'fruechte': ['Apfel', 'Banane']}
dd_int = defaultdict(int)
for char in "abracadabra":
dd_int[char] += 1
print(f"ZĂ€hlungen: {dict(dd_int)}")
# â ZĂ€hlungen: {'a': 5, 'b': 2, 'r': 2, 'c': 1, 'd': 1}
dd_set = defaultdict(set)
dd_set["staedte"].add("Berlin")
dd_set["staedte"].add("MĂŒnchen")
print(f"Menge: {dict(dd_set)}")
# â Menge: {'staedte': {'Berlin', 'MĂŒnchen'}}
- Entfernt Boilerplate-Code wie
if key not in d: d[key] = []. - Macht Code sauberer und sicherer.
11. dataclass â Datenklassen
Dekorator, der automatisch __init__, __repr__, __eq__ usw. generiert.
from dataclasses import dataclass
@dataclass
class Person:
name: str
alter: int
stadt: str = "Nicht angegeben"
anna = Person("Anna", 25)
print(f"Objekt: {anna}")
# â Objekt: Person(name='Anna', alter=25, stadt='Nicht angegeben')
print(f"Name: {anna.name}")
# â Name: Anna
anna.alter = 26
print(f"Nach Ănderung: {anna}")
# â Nach Ănderung: Person(name='Anna', alter=26, stadt='Nicht angegeben')
bob = Person("Bob", 30)
print(f"Anna == Bob: {anna == bob}")
# â Anna == Bob: False
@dataclass(frozen=True)
class UnveraenderbarePerson:
name: str
alter: int
ivan = UnveraenderbarePerson("Ivan", 40)
# ivan.alter = 41 â FrozenInstanceError
- Ersetzt manuelles Schreiben von
__init__,__repr__,__eq__. - Ideal fĂŒr DTOs, Konfigurationen, Modelle.
12. UserList â benutzerdefinierte Listen
Erbt von collections.UserList. Wird verwendet, um Listen mit benutzerdefiniertem Verhalten zu erstellen.
from collections import UserList
class ProtokollierteListe(UserList):
def append(self, item):
print(f"[LOG] HinzufĂŒgen: {item}")
super().append(item)
def remove(self, item):
print(f"[LOG] Entfernen: {item}")
super().remove(item)
log_list = ProtokollierteListe([1, 2, 3])
print(f"Initial: {log_list}")
# â Initial: [1, 2, 3]
log_list.append(4)
# â [LOG] HinzufĂŒgen: 4
print(f"Nach append: {log_list}")
# â Nach append: [1, 2, 3, 4]
log_list.remove(2)
# â [LOG] Entfernen: 2
print(f"Nach remove: {log_list}")
# â Nach remove: [1, 3, 4]
- NĂŒtzlich zum HinzufĂŒgen von Logging, Validierung oder zum Ăndern des Standardlistenverhaltens.
13. UserDict â benutzerdefinierte WörterbĂŒcher
Erbt von collections.UserDict. Wird verwendet, um WörterbĂŒcher mit benutzerdefiniertem Verhalten zu erstellen.
from collections import UserDict
class KleinschreibDict(UserDict):
def __setitem__(self, key, value):
key = key.lower() if isinstance(key, str) else key
super().__setitem__(key, value)
def __getitem__(self, key):
key = key.lower() if isinstance(key, str) else key
return super().__getitem__(key)
ld = KleinschreibDict()
ld["Name"] = "Anna"
print(f"Wert fĂŒr 'Name': {ld['Name']}")
# â Wert fĂŒr 'Name': Anna
print(f"Wert fĂŒr 'name': {ld['name']}")
# â Wert fĂŒr 'name': Anna
print(f"SchlĂŒssel: {list(ld.keys())}")
# â SchlĂŒssel: ['name']
- Wird zur SchlĂŒsselnormalisierung, Validierung, Protokollierung, Caching usw. verwendet.
đ Speicher- und Leistungsvergleich
Die Wahl der Sammlung beeinflusst Leistung und Speicherverbrauch. Hier praktische Benchmarks.
1. Speicher: list vs tuple vs array.array
import sys
from array import array
n = 1_000_000
data = list(range(n))
data_t = tuple(range(n))
data_a = array('i', range(n))
print(f"list: {sys.getsizeof(data) / 1024 / 1024:.2f} MB")
# â list: 8.00 MB
print(f"tuple: {sys.getsizeof(data_t) / 1024 / 1024:.2f} MB")
# â tuple: 8.00 MB
print(f"array: {sys.getsizeof(data_a) / 1024 / 1024:.2f} MB")
# â array: 3.81 MB
array.arrayverbraucht ~2x weniger Speicher fĂŒr Zahlen.listundtupleverbrauchen Ă€hnlichen Speicher, abertupleist etwas schneller bei Iteration.
2. Zugriffsgeschwindigkeit: list vs tuple vs array.array
import time
def time_access(collection, name):
start = time.perf_counter()
total = 0
for i in range(len(collection)):
total += collection[i]
end = time.perf_counter()
print(f"{name}: {end - start:.4f} Sekunden")
n = 10_000_000
lst = list(range(n))
tpl = tuple(range(n))
arr = array('i', range(n))
time_access(lst, "list") # â list: 1.2000 Sekunden
time_access(tpl, "tuple") # â tuple: 1.0000 Sekunden
time_access(arr, "array") # â array: 0.8000 Sekunden
array.arrayist am schnellsten fĂŒr numerische Daten.tupleist 10â20% schneller alslist.- Unterschied bemerkbar bei groĂen Datenmengen.
3. Speicher: dict vs SimpleNamespace vs dataclass
d = {"name": "A", "alter": 25, "stadt": "X", "hobby": "Y", "job": "Z"}
ns = SimpleNamespace(name="A", alter=25, stadt="X", hobby="Y", job="Z")
dc = PersonDC("A", 25, "X", "Y", "Z")
print(f"dict: {sys.getsizeof(d)} Bytes") # â 232
print(f"SimpleNamespace: {sys.getsizeof(ns)} Bytes") # â 64
print(f"dataclass: {sys.getsizeof(dc)} Bytes") # â 64
print(f"ns.__dict__: {sys.getsizeof(ns.__dict__)} Bytes") # â 232
SimpleNamespaceunddataclassverbrauchen so viel Speicher wiedictwegen__dict__.- Verwenden Sie
__slots__zur Speicherersparnis.
4. Speicheroptimierung: dataclass mit __slots__
@dataclass
class PersonSlots:
__slots__ = ("name", "alter", "stadt", "hobby", "job")
name: str
alter: int
stadt: str
hobby: str
job: str
dc_slots = PersonSlots("A", 25, "X", "Y", "Z")
print(f"dataclass + slots: {sys.getsizeof(dc_slots)} Bytes")
# â 80 Bytes
# dc_slots.neu = "Wert" â AttributeError
__slots__spart Speicher und beschleunigt Attributzugriff.- Nachteil: keine dynamischen Attribute.
5. Suchgeschwindigkeit: list vs set
n = 1_000_000
lst = list(range(n))
st = set(range(n))
def time_in(collection, target, name):
start = time.perf_counter()
for _ in range(1000):
_ = target in collection
end = time.perf_counter()
print(f"{name} (Suche {target}): {end - start:.4f} Sekunden")
time_in(lst, 999_999, "list") # â 10.0000 Sekunden
time_in(st, 999_999, "set") # â 0.0005 Sekunden
setist tausendmal schneller alslistfĂŒr MitgliedschaftsprĂŒfungen.- Immer
setverwenden, wenn hĂ€ufigx in collectiongeprĂŒft wird.
6. Speicher: set vs frozenset
s = set(range(1000))
fs = frozenset(range(1000))
print(f"set: {sys.getsizeof(s)} Bytes") # â 32792
print(f"frozenset: {sys.getsizeof(fs)} Bytes") # â 32792
frozensetundsetverbrauchen identischen Speicher.- Unterschied nur in der VerÀnderbarkeit.
7. HinzufĂŒgungsgeschwindigkeit: list.append vs deque.append vs deque.appendleft
from collections import deque
import time
def time_append(collection, n, method='append'):
start = time.perf_counter()
for i in range(n):
if method == 'appendleft' and hasattr(collection, 'appendleft'):
collection.appendleft(i)
else:
collection.append(i)
end = time.perf_counter()
return end - start
n = 100_000
lst = []
dq = deque()
time_list_append = time_append(lst, n) # â 0.0100 Sekunden
time_deque_append = time_append(dq, n) # â 0.0100 Sekunden
time_deque_appendleft = time_append(deque(), n, 'appendleft') # â 0.0100 Sekunden
# list.insert(0):
lst = []
start = time.perf_counter()
for i in range(n):
lst.insert(0, i)
end = time.perf_counter()
print(f"list.insert(0): {end - start:.4f} Sekunden") # â 5.0000 Sekunden
deque.appendleftist O(1), im Gegensatz zulist.insert(0)(O(n)).- Verwenden Sie
dequefĂŒr hĂ€ufige Operationen an beiden Enden.
đ§ Leistungsempfehlungen
| Situation | Verwenden | Grund |
|---|---|---|
| Zahlen speichern, Speicher kritisch | array.array | 2x weniger Speicher, schneller Zugriff |
| UnverÀnderliche Daten | tuple | Schneller als list, sicherer |
HĂ€ufige x in collection-PrĂŒfungen | set / frozenset | O(1) vs O(n) von list |
| Operationen an beiden Enden | deque | appendleft/popleft in O(1) |
| Strukturierte Daten, Speicher kritisch | dataclass + __slots__ | Kein __dict__, weniger Speicher |
| HĂ€ufigkeiten zĂ€hlen | Counter | FĂŒr diese Aufgabe optimiert |
| Benutzerdefiniertes Verhalten | UserList / UserDict | Sichere Erweiterung integrierter Sammlungen |
đ Sammlungsvergleich
| Typ | Geordnet | VerÀnderbar | Eindeutige Elemente | Indexzugriff | Duplikate |
|---|---|---|---|---|---|
list | â Ja | â Ja | â Nein | â Ja | â Ja |
tuple | â Ja | â Nein | â Nein | â Ja | â Ja |
dict | â Ja* | â Ja | Nur SchlĂŒssel | â Nein | Werte: â |
set | â Nein | â Ja | â Ja | â Nein | â Nein |
frozenset | â Nein | â Nein | â Ja | â Nein | â Nein |
SimpleNamespace | â Ja (Attrs) | â Ja | â Nein (Attrs können semantisch doppelt sein) | â Nein | â Ja |
namedtuple | â Ja | â Nein | â Nein | â Ja | â Ja |
deque | â Ja | â Ja | â Nein | â Ja | â Ja |
Counter | â Nein | â Ja | â Nein | â Nein (aber hat SchlĂŒssel) | â Ja |
defaultdict | â Ja* | â Ja | Nur SchlĂŒssel | â Nein | Werte: â |
dataclass | â Ja (Felder) | â Ja (wenn nicht frozen) | â Nein | â Nein | â Ja |
UserList | â Ja | â Ja | â Nein | â Ja | â Ja |
UserDict | â Ja* | â Ja | Nur SchlĂŒssel | â Nein | Werte: â |
str | â Ja | â Nein | â Nein | â Ja | â Ja |
bytes | â Ja | â Nein | â Nein | â Ja | â Ja |
bytearray | â Ja | â Ja | â Nein | â Ja | â Ja |
range | â Ja | â Nein | â Nein | â Ja | â Nein |
array.array | â Ja | â Ja | â Nein | â Ja | â Ja |
ChainMap | â Ja* | â Ja | Nur SchlĂŒssel | â Nein | Werte: â |
Enum | â Ja | â Nein | â Ja (Mitglieder) | â Nein | â Nein |
- â seit Python 3.7 behalten
dict,defaultdict,UserDict,ChainMapEinfĂŒgereihenfolge bei.
đĄ Wann was verwenden?
| Aufgabe | Sammlung |
|---|---|
| VerÀnderbare Sequenz | list / deque / UserList / bytearray |
| UnverÀnderliche Daten | tuple / namedtuple / frozenset / str / bytes |
| Schnelle Suche, Duplikate entfernen | set / frozenset |
| Strukturierte Daten | dict / dataclass / SimpleNamespace / UserDict / TypedDict |
| Als Dictionary-SchlĂŒssel verwendbar | frozenset |
| TemporÀre Objekte mit Punktzugriff | SimpleNamespace / dataclass |
| HÀufigkeiten zÀhlen | Counter |
| Standardwerte fĂŒr SchlĂŒssel | defaultdict |
| Effiziente Endoperationen | deque |
| Benutzerdefiniertes Listenverhalten | UserList |
| Benutzerdefiniertes Dict-Verhalten | UserDict |
| BinÀrdaten | bytes / bytearray / array.array |
| Konfigurationen mit Hierarchie | ChainMap |
| Benannte Konstanten | Enum |
| Faule Sequenzen | range / Generatoren |