Einführung
In diesem Lab lernen Sie, Speicher-effiziente Methoden zur Speicherung großer Datensätze in Python zu erkunden. Sie werden auch verschiedene Möglichkeiten zur Darstellung von Datensätzen entdecken, wie z. B. Tupel, Wörterbücher, Klassen und benannte Tupel.
Darüber hinaus werden Sie den Speicherverbrauch verschiedener Datenstrukturen vergleichen. Das Verständnis der Kompromisse zwischen diesen Strukturen ist für Python - Benutzer, die Datenanalysen durchführen, von Wert, da es bei der Optimierung des Codes hilft.
Erkundung des Datensatzes
Beginnen wir unsere Reise mit einem genauen Blick auf den Datensatz, mit dem wir arbeiten werden. Die Datei ctabus.csv ist eine CSV-Datei (Comma-Separated Values, Komma-getrennte Werte). CSV-Dateien sind eine gängige Methode zur Speicherung tabellarischer Daten, wobei jede Zeile eine Reihe darstellt und die Werte innerhalb einer Reihe durch Kommas getrennt sind. Diese spezielle Datei enthält tägliche Fahrgastzahlen für das Bussystem der Chicago Transit Authority (CTA) im Zeitraum vom 1. Januar 2001 bis zum 31. August 2013.
Entpacken Sie die Datei und entfernen Sie die Zip-Datei:
cd /home/labex/project
unzip ctabus.csv.zip
rm ctabus.csv.zip
Um die Struktur dieser Datei zu verstehen, werfen wir zunächst einen Blick hinein. Wir werden Python verwenden, um die Datei zu lesen und einige Zeilen auszugeben. Öffnen Sie ein Terminal und führen Sie den folgenden Python-Code aus:
f = open('/home/labex/project/ctabus.csv')
print(next(f)) ## Read the header line
print(next(f)) ## Read the first data line
print(next(f)) ## Read the second data line
f.close()
In diesem Code öffnen wir zuerst die Datei mit der Funktion open und weisen sie der Variablen f zu. Die Funktion next wird verwendet, um die nächste Zeile aus der Datei zu lesen. Wir verwenden sie dreimal: das erste Mal, um die Kopfzeile (header line) zu lesen, die normalerweise die Namen der Spalten im Datensatz enthält. Das zweite und dritte Mal lesen wir die erste bzw. zweite Datenzeile. Schließlich schließen wir die Datei mit der Methode close, um Systemressourcen freizugeben.
Sie sollten eine ähnliche Ausgabe wie diese sehen:
route,date,daytype,rides
3,01/01/2001,U,7354
4,01/01/2001,U,9288
Diese Ausgabe zeigt, dass die Datei 4 Datenspalten hat. Lassen Sie uns aufschlüsseln, was jede Spalte darstellt:
route: Dies ist der Name oder die Nummer der Buslinie (bus route). Es ist die erste Spalte (Spalte 0) im Datensatz.date: Dies ist eine Datumszeichenfolge (date string) im Format MM/TT/JJJJ. Dies ist die zweite Spalte (Spalte 1).daytype: Dies ist ein Tagestyp-Code (day type code), der die dritte Spalte (Spalte 2) ist.- U = Sonntag/Feiertag (Sunday/Holiday)
- A = Samstag (Saturday)
- W = Wochentag (Weekday)
rides: Diese Spalte erfasst die Gesamtzahl der Fahrgäste als ganze Zahl (integer). Es ist die vierte Spalte (Spalte 3).
Die Spalte rides gibt an, wie viele Personen an einem bestimmten Tag in eine bestimmte Buslinie eingestiegen sind. Aus der obigen Ausgabe können wir beispielsweise ersehen, dass am 1. Januar 2001 7.354 Personen mit der Buslinie 3 gefahren sind.
Finden wir nun heraus, wie viele Zeilen sich in der Datei befinden. Die Kenntnis der Anzahl der Zeilen gibt uns eine Vorstellung von der Größe unseres Datensatzes. Führen Sie den folgenden Python-Code aus:
with open('/home/labex/project/ctabus.csv') as f:
line_count = sum(1 for line in f)
print(f"Total lines in the file: {line_count}")
In diesem Code verwenden wir die with-Anweisung, um die Datei zu öffnen. Der Vorteil der Verwendung von with besteht darin, dass es sich automatisch um das Schließen der Datei kümmert, wenn wir damit fertig sind. Wir verwenden dann einen Generatorausdruck (1 for line in f), um eine Sequenz von Einsen zu erstellen, eine für jede Zeile in der Datei. Die Funktion sum addiert alle diese Einsen und ergibt die Gesamtzahl der Zeilen in der Datei. Schließlich geben wir das Ergebnis aus.
Dies sollte ungefähr 577.564 Zeilen ausgeben, was bedeutet, dass wir es mit einem umfangreichen Datensatz zu tun haben. Dieser große Datensatz wird uns viele Daten liefern, die wir analysieren und aus denen wir Erkenntnisse gewinnen können.
Messen des Speicherverbrauchs mit verschiedenen Speichermethoden
In diesem Schritt werden wir untersuchen, wie verschiedene Arten der Datenspeicherung den Speicherverbrauch beeinflussen können. Der Speicherverbrauch ist ein wichtiger Aspekt der Programmierung, insbesondere wenn es um große Datensätze geht. Um den Speicherverbrauch unseres Python-Codes zu messen, verwenden wir das tracemalloc-Modul von Python. Dieses Modul ist sehr nützlich, da es uns ermöglicht, die von Python vorgenommenen Speicherzuweisungen zu verfolgen. Dadurch können wir sehen, wie viel Speicher unsere Datenspeichermethoden verbrauchen.
Methode 1: Speichern der gesamten Datei als einzelne Zeichenkette
Beginnen wir damit, eine neue Python-Datei zu erstellen. Navigieren Sie in das Verzeichnis /home/labex/project und erstellen Sie eine Datei mit dem Namen memory_test1.py. Sie können einen Texteditor verwenden, um diese Datei zu öffnen. Sobald die Datei geöffnet ist, fügen Sie den folgenden Code hinzu. Dieser Code liest den gesamten Inhalt einer Datei als einzelne Zeichenkette und misst den Speicherverbrauch.
## memory_test1.py
import tracemalloc
def test_single_string():
## Start tracking memory
tracemalloc.start()
## Read the entire file as a single string
with open('/home/labex/project/ctabus.csv') as f:
data = f.read()
## Get memory usage statistics
current, peak = tracemalloc.get_traced_memory()
print(f"File length: {len(data)} characters")
print(f"Current memory usage: {current/1024/1024:.2f} MB")
print(f"Peak memory usage: {peak/1024/1024:.2f} MB")
## Stop tracking memory
tracemalloc.stop()
if __name__ == "__main__":
test_single_string()
Nachdem Sie den Code hinzugefügt haben, speichern Sie die Datei. Um dieses Skript auszuführen, öffnen Sie Ihr Terminal und geben Sie den folgenden Befehl ein:
python3 /home/labex/project/memory_test1.py
Wenn Sie das Skript ausführen, sollten Sie eine Ausgabe ähnlich der folgenden sehen:
File length: 12361039 characters
Current memory usage: 11.80 MB
Peak memory usage: 23.58 MB
Die genauen Zahlen können auf Ihrem System unterschiedlich sein, aber im Allgemeinen werden Sie feststellen, dass der aktuelle Speicherverbrauch etwa 12 MB und der Spitzen-Speicherverbrauch etwa 24 MB beträgt.
Methode 2: Speichern als Liste von Zeichenketten
Als Nächstes testen wir eine andere Möglichkeit, die Daten zu speichern. Erstellen Sie eine neue Datei mit dem Namen memory_test2.py im gleichen Verzeichnis /home/labex/project. Öffnen Sie diese Datei im Editor und fügen Sie den folgenden Code hinzu. Dieser Code liest die Datei und speichert jede Zeile als separate Zeichenkette in einer Liste und misst dann den Speicherverbrauch.
## memory_test2.py
import tracemalloc
def test_list_of_strings():
## Start tracking memory
tracemalloc.start()
## Read the file as a list of strings (one string per line)
with open('/home/labex/project/ctabus.csv') as f:
lines = f.readlines()
## Get memory usage statistics
current, peak = tracemalloc.get_traced_memory()
print(f"Number of lines: {len(lines)}")
print(f"Current memory usage: {current/1024/1024:.2f} MB")
print(f"Peak memory usage: {peak/1024/1024:.2f} MB")
## Stop tracking memory
tracemalloc.stop()
if __name__ == "__main__":
test_list_of_strings()
Speichern Sie die Datei und führen Sie dann das Skript mit dem folgenden Befehl im Terminal aus:
python3 /home/labex/project/memory_test2.py
Sie sollten eine Ausgabe ähnlich der folgenden sehen:
Number of lines: 577564
Current memory usage: 43.70 MB
Peak memory usage: 43.74 MB
Beachten Sie, dass der Speicherverbrauch im Vergleich zur vorherigen Methode, die Daten als einzelne Zeichenkette zu speichern, deutlich gestiegen ist. Dies liegt daran, dass jede Zeile in der Liste ein separates Python-Zeichenkettenobjekt ist, und jedes Objekt hat seinen eigenen Speicher-Overhead.
Verständnis der Speicherdifferenz
Der Unterschied im Speicherverbrauch zwischen den beiden Ansätzen zeigt ein wichtiges Konzept in der Python-Programmierung, das als Objekt-Overhead (engl. object overhead) bezeichnet wird. Wenn Sie Daten als Liste von Zeichenketten speichern, ist jede Zeichenkette ein separates Python-Objekt. Jedes Objekt hat einige zusätzliche Speicheranforderungen, die Folgendes umfassen:
- Der Python-Objektheader (normalerweise 16 - 24 Bytes pro Objekt). Dieser Header enthält Informationen über das Objekt, wie z. B. seinen Typ und die Referenzzählung.
- Die eigentliche Zeichenkettenrepräsentation selbst, die die Zeichen der Zeichenkette speichert.
- Speicherausrichtungsauffüllung (engl. memory alignment padding). Dies ist zusätzlicher Speicherplatz, der hinzugefügt wird, um sicherzustellen, dass die Speicheradresse des Objekts richtig ausgerichtet ist, um einen effizienten Zugriff zu ermöglichen.
Andererseits, wenn Sie den gesamten Dateiinhalt als einzelne Zeichenkette speichern, gibt es nur ein Objekt und somit nur einen Satz von Overhead. Dies macht es bei Betrachtung der Gesamtgröße der Daten speichereffizienter.
Bei der Gestaltung von Programmen, die mit großen Datensätzen arbeiten, müssen Sie diesen Kompromiss zwischen Speichereffizienz und Datenzugänglichkeit berücksichtigen. Manchmal kann es bequemer sein, auf Daten zuzugreifen, wenn sie in einer Liste von Zeichenketten gespeichert sind, aber dies verbraucht mehr Speicher. Andere Male können Sie die Speichereffizienz priorisieren und sich entscheiden, die Daten als einzelne Zeichenkette zu speichern.
Arbeiten mit strukturierten Daten mithilfe von Tupeln
Bisher haben wir uns mit der Speicherung von Roh-Text-Daten beschäftigt. Bei der Datenanalyse müssen wir die Daten jedoch in der Regel in organisiertere und strukturierte Formate transformieren. Dies erleichtert es, verschiedene Operationen auszuführen und Erkenntnisse aus den Daten zu gewinnen. In diesem Schritt lernen wir, wie man Daten mithilfe des csv-Moduls als Liste von Tupeln liest. Tupel sind eine einfache und nützliche Datenstruktur in Python, die mehrere Werte aufnehmen kann.
Erstellen einer Lesefunktion mit Tupeln
Erstellen wir eine neue Datei mit dem Namen readrides.py im Verzeichnis /home/labex/project. Diese Datei enthält den Code, um die Daten aus einer CSV-Datei zu lesen und als Liste von Tupeln zu speichern.
## readrides.py
import csv
import tracemalloc
def read_rides_as_tuples(filename):
'''
Read the bus ride data as a list of tuples
'''
records = []
with open(filename) as f:
rows = csv.reader(f)
headings = next(rows) ## Skip headers
for row in rows:
route = row[0]
date = row[1]
daytype = row[2]
rides = int(row[3])
record = (route, date, daytype, rides)
records.append(record)
return records
if __name__ == '__main__':
tracemalloc.start()
rows = read_rides_as_tuples('/home/labex/project/ctabus.csv')
current, peak = tracemalloc.get_traced_memory()
print(f'Number of records: {len(rows)}')
print(f'First record: {rows[0]}')
print(f'Second record: {rows[1]}')
print(f'Memory Use: Current {current/1024/1024:.2f} MB, Peak {peak/1024/1024:.2f} MB')
Dieses Skript definiert eine Funktion namens read_rides_as_tuples. Hier ist, was sie Schritt für Schritt macht:
- Sie öffnet die CSV-Datei, die durch den
filename-Parameter angegeben wird. Dadurch können wir auf die Daten in der Datei zugreifen. - Sie verwendet das
csv-Modul, um jede Zeile der Datei zu analysieren. Diecsv.reader-Funktion hilft uns, die Zeilen in einzelne Werte aufzuteilen. - Sie extrahiert die vier Felder (Linie, Datum, Tagestyp und Anzahl der Fahrten) aus jeder Zeile. Diese Felder sind für unsere Datenanalyse wichtig.
- Sie konvertiert das Feld 'rides' in eine Ganzzahl. Dies ist notwendig, da die Daten in der CSV-Datei zunächst im Zeichenkettenformat vorliegen und wir einen numerischen Wert für Berechnungen benötigen.
- Sie erstellt ein Tupel mit diesen vier Werten. Tupel sind unveränderlich, was bedeutet, dass ihre Werte nach der Erstellung nicht geändert werden können.
- Sie fügt das Tupel einer Liste namens
recordshinzu. Diese Liste enthält alle Datensätze aus der CSV-Datei.
Jetzt führen wir das Skript aus. Öffnen Sie Ihr Terminal und geben Sie den folgenden Befehl ein:
python3 /home/labex/project/readrides.py
Sie sollten eine Ausgabe ähnlich der folgenden sehen:
Number of records: 577563
First record: ('3', '01/01/2001', 'U', 7354)
Second record: ('4', '01/01/2001', 'U', 9288)
Memory Use: Current 89.12 MB, Peak 89.15 MB
Beachten Sie, dass der Speicherverbrauch im Vergleich zu unseren vorherigen Beispielen gestiegen ist. Es gibt einige Gründe dafür:
- Wir speichern die Daten jetzt in einem strukturierten Format (Tupeln). Strukturierte Daten erfordern in der Regel mehr Speicher, da sie eine definierte Organisation haben.
- Jeder Wert im Tupel ist ein separates Python-Objekt. Python-Objekte haben einen gewissen Overhead, der zum erhöhten Speicherverbrauch beiträgt.
- Wir haben eine zusätzliche Listenstruktur, die alle diese Tupel enthält. Listen nehmen auch Speicherplatz in Anspruch, um ihre Elemente zu speichern.
Der Vorteil dieses Ansatzes ist, dass unsere Daten jetzt richtig strukturiert und für die Analyse bereit sind. Wir können leicht auf bestimmte Felder jedes Datensatzes über den Index zugreifen. Beispielsweise:
## Example of accessing tuple elements (add this to readrides.py file to try it)
first_record = rows[0]
route = first_record[0]
date = first_record[1]
daytype = first_record[2]
rides = first_record[3]
print(f"Route: {route}, Date: {date}, Day type: {daytype}, Rides: {rides}")
Allerdings ist der Zugriff auf Daten über numerische Indizes nicht immer intuitiv. Es kann schwierig sein, sich zu merken, welcher Index welchem Feld entspricht, insbesondere wenn es viele Felder gibt. Im nächsten Schritt werden wir andere Datenstrukturen untersuchen, die unseren Code lesbarer und wartbarer machen können.
Vergleich verschiedener Datenstrukturen
In Python werden Datenstrukturen verwendet, um verwandte Daten zu organisieren und zu speichern. Sie sind wie Container, die verschiedene Arten von Informationen auf strukturierte Weise aufnehmen. In diesem Schritt vergleichen wir verschiedene Datenstrukturen und sehen, wie viel Speicher sie verbrauchen.
Erstellen wir eine neue Datei namens compare_structures.py im Verzeichnis /home/labex/project. Diese Datei enthält den Code, um Daten aus einer CSV-Datei zu lesen und in verschiedenen Datenstrukturen zu speichern.
## compare_structures.py
import csv
import tracemalloc
from collections import namedtuple
## Define a named tuple for rides data
RideRecord = namedtuple('RideRecord', ['route', 'date', 'daytype', 'rides'])
## A named tuple is a lightweight class that allows you to access its fields by name.
## It's like a tuple, but with named attributes.
## Define a class with __slots__ for memory optimization
class SlottedRideRecord:
__slots__ = ['route', 'date', 'daytype', 'rides']
def __init__(self, route, date, daytype, rides):
self.route = route
self.date = date
self.daytype = daytype
self.rides = rides
## A class with __slots__ is a memory - optimized class.
## It avoids using an instance dictionary, which saves memory.
## Define a regular class for rides data
class RegularRideRecord:
def __init__(self, route, date, daytype, rides):
self.route = route
self.date = date
self.daytype = daytype
self.rides = rides
## A regular class is an object - oriented way to represent data.
## It has named attributes and can have methods.
## Function to read data as tuples
def read_as_tuples(filename):
records = []
with open(filename) as f:
rows = csv.reader(f)
next(rows) ## Skip headers
for row in rows:
record = (row[0], row[1], row[2], int(row[3]))
records.append(record)
return records
## This function reads data from a CSV file and stores it as tuples.
## Tuples are immutable sequences, and you access their elements by numeric index.
## Function to read data as dictionaries
def read_as_dicts(filename):
records = []
with open(filename) as f:
rows = csv.reader(f)
headers = next(rows) ## Get headers
for row in rows:
record = {
'route': row[0],
'date': row[1],
'daytype': row[2],
'rides': int(row[3])
}
records.append(record)
return records
## This function reads data from a CSV file and stores it as dictionaries.
## Dictionaries use key - value pairs, so you can access elements by their names.
## Function to read data as named tuples
def read_as_named_tuples(filename):
records = []
with open(filename) as f:
rows = csv.reader(f)
next(rows) ## Skip headers
for row in rows:
record = RideRecord(row[0], row[1], row[2], int(row[3]))
records.append(record)
return records
## This function reads data from a CSV file and stores it as named tuples.
## Named tuples combine the efficiency of tuples with the readability of named access.
## Function to read data as regular class instances
def read_as_regular_classes(filename):
records = []
with open(filename) as f:
rows = csv.reader(f)
next(rows) ## Skip headers
for row in rows:
record = RegularRideRecord(row[0], row[1], row[2], int(row[3]))
records.append(record)
return records
## This function reads data from a CSV file and stores it as instances of a regular class.
## Regular classes allow you to add methods to your data.
## Function to read data as slotted class instances
def read_as_slotted_classes(filename):
records = []
with open(filename) as f:
rows = csv.reader(f)
next(rows) ## Skip headers
for row in rows:
record = SlottedRideRecord(row[0], row[1], row[2], int(row[3]))
records.append(record)
return records
## This function reads data from a CSV file and stores it as instances of a slotted class.
## Slotted classes are memory - optimized and still provide named access.
## Function to measure memory usage
def measure_memory(func, filename):
tracemalloc.start()
records = func(filename)
current, peak = tracemalloc.get_traced_memory()
## Demonstrate how to use each data structure
first_record = records[0]
if func.__name__ == 'read_as_tuples':
route, date, daytype, rides = first_record
elif func.__name__ == 'read_as_dicts':
route = first_record['route']
date = first_record['date']
daytype = first_record['daytype']
rides = first_record['rides']
else: ## named tuples and classes
route = first_record.route
date = first_record.date
daytype = first_record.daytype
rides = first_record.rides
print(f"Structure type: {func.__name__}")
print(f"Record count: {len(records)}")
print(f"Example access: Route={route}, Date={date}, Rides={rides}")
print(f"Current memory: {current/1024/1024:.2f} MB")
print(f"Peak memory: {peak/1024/1024:.2f} MB")
print("-" * 50)
tracemalloc.stop()
return current
if __name__ == "__main__":
filename = '/home/labex/project/ctabus.csv'
## Run all memory tests
print("Memory usage comparison for different data structures:\n")
results = []
for reader_func in [
read_as_tuples,
read_as_dicts,
read_as_named_tuples,
read_as_regular_classes,
read_as_slotted_classes
]:
memory = measure_memory(reader_func, filename)
results.append((reader_func.__name__, memory))
## Sort by memory usage (lowest first)
results.sort(key=lambda x: x[1])
print("\nRanking by memory efficiency (most efficient first):")
for i, (name, memory) in enumerate(results, 1):
print(f"{i}. {name}: {memory/1024/1024:.2f} MB")
Führen Sie das Skript aus, um die Vergleichsergebnisse zu sehen:
python3 /home/labex/project/compare_structures.py
Die Ausgabe zeigt den Speicherverbrauch für jede Datenstruktur sowie eine Rangliste von der speichereffizientesten bis zur am wenigsten speichereffizienten.
Verständnis der verschiedenen Datenstrukturen
Tupel:
- Tupel sind leichte und unveränderliche Sequenzen. Das bedeutet, dass Sie die Elemente eines Tupels nach seiner Erstellung nicht ändern können.
- Sie greifen auf die Elemente eines Tupels über ihren numerischen Index zu, wie z. B.
record[0],record[1]usw. - Sie sind sehr speichereffizient, da sie eine einfache Struktur haben.
- Allerdings können sie weniger lesbar sein, da Sie sich den Index jedes Elements merken müssen.
Wörterbücher (Dictionaries):
- Wörterbücher verwenden Schlüssel-Wert-Paare, was es Ihnen ermöglicht, auf die Elemente über ihre Namen zuzugreifen.
- Sie sind lesbarer, z. B. können Sie
record['route'],record['date']usw. verwenden. - Sie haben einen höheren Speicherverbrauch aufgrund des Hash-Tabellen-Overheads, der zum Speichern der Schlüssel-Wert-Paare verwendet wird.
- Sie sind flexibel, da Sie Felder leicht hinzufügen oder entfernen können.
Benannte Tupel (Named Tuples):
- Benannte Tupel kombinieren die Effizienz von Tupeln mit der Möglichkeit, auf die Elemente über ihren Namen zuzugreifen.
- Sie können auf die Elemente mit der Punktnotation zugreifen, wie z. B.
record.route,record.dateusw. - Sie sind unveränderlich, genau wie normale Tupel.
- Sie sind speichereffizienter als Wörterbücher.
Normale Klassen (Regular Classes):
- Normale Klassen folgen einem objektorientierten Ansatz und haben benannte Attribute.
- Sie können auf die Attribute mit der Punktnotation zugreifen, wie z. B.
record.route,record.dateusw. - Sie können Methoden zu einer normalen Klasse hinzufügen, um Verhalten zu definieren.
- Sie verbrauchen mehr Speicher, da jede Instanz ein Instanz-Wörterbuch zum Speichern ihrer Attribute hat.
Klassen mit
__slots__:- Klassen mit
__slots__sind speichergerecht optimierte Klassen. Sie vermeiden die Verwendung eines Instanz-Wörterbuchs, was Speicher spart. - Sie bieten immer noch benannten Zugriff auf die Attribute, wie z. B.
record.route,record.dateusw. - Sie beschränken das Hinzufügen neuer Attribute nach der Erstellung des Objekts.
- Sie sind speichereffizienter als normale Klassen.
- Klassen mit
Wann welche Methode verwenden
- Tupel: Verwenden Sie Tupel, wenn Speicher ein kritischer Faktor ist und Sie nur einfachen indizierten Zugriff auf Ihre Daten benötigen.
- Wörterbücher: Verwenden Sie Wörterbücher, wenn Sie Flexibilität benötigen, z. B. wenn die Felder in Ihren Daten variieren können.
- Benannte Tupel: Verwenden Sie benannte Tupel, wenn Sie sowohl Lesbarkeit als auch Speichereffizienz benötigen.
- Normale Klassen: Verwenden Sie normale Klassen, wenn Sie Verhalten (Methoden) zu Ihren Daten hinzufügen müssen.
- Klassen mit
__slots__: Verwenden Sie Klassen mit__slots__, wenn Sie Verhalten und maximale Speichereffizienz benötigen.
Durch die Wahl der richtigen Datenstruktur für Ihre Bedürfnisse können Sie die Leistung und den Speicherverbrauch Ihrer Python-Programme erheblich verbessern, insbesondere wenn Sie mit großen Datensätzen arbeiten.
Zusammenfassung
In diesem Lab haben Sie verschiedene Methoden kennengelernt, um Datensätze in Python darzustellen, und deren Speichereffizienz analysiert. Zunächst haben Sie die grundlegende Struktur eines CSV-Datensatzes verstanden und Methoden zur Roh-Text-Speicherung verglichen. Anschließend haben Sie mit strukturierten Daten mithilfe von Tupeln gearbeitet und fünf verschiedene Datenstrukturen implementiert: Tupel, Wörterbücher (Dictionaries), benannte Tupel (Named Tuples), normale Klassen (Regular Classes) und Klassen mit __slots__.
Wichtige Erkenntnisse sind, dass verschiedene Datenstrukturen Kompromisse zwischen Speichereffizienz, Lesbarkeit und Funktionalität bieten. Der Overhead von Python-Objekten hat einen erheblichen Einfluss auf den Speicherverbrauch bei großen Datensätzen, und die Wahl der Datenstruktur kann den Speicherverbrauch stark beeinflussen. Benannte Tupel und Klassen mit __slots__ sind gute Kompromisse zwischen Speichereffizienz und Code-Lesbarkeit. Diese Konzepte sind für Python-Entwickler bei der Datenverarbeitung von Wert, insbesondere wenn es um die Verarbeitung großer Datensätze geht, bei denen die Speichereffizienz von entscheidender Bedeutung ist.