Die integrierten Funktionen von Python: Eine vollständige Erkundung


Python verfügt über viele integrierte Funktionen, die Sie direkt verwenden können, ohne etwas importieren zu müssen. Diese Funktionen decken eine Vielzahl gängiger Programmieraufgaben ab, darunter die Durchführung mathematischer Operationen, die Arbeit mit integrierten Datentypen, die Verarbeitung iterierbarer Daten, die Verarbeitung von Eingaben und Ausgaben in Ihren Programmen, die Arbeit mit Bereichen und mehr.

In diesem Tutorial werden Sie:

  • Lernen Sie die integrierten Funktionen von Python kennen
  • Erfahren Sie mehr über häufige Anwendungsfälle der integrierten Funktionen von Python
  • Nutzen Sie diese Funktionen, um praktische Probleme zu lösen

Um dieses Tutorial optimal nutzen zu können, müssen Sie mit der Python-Programmierung vertraut sein, einschließlich Themen wie der Arbeit mit integrierten Datentypen, Funktionen, Klassen, Dekoratoren, Bereichen und dem Importsystem.

Integrierte Funktionen in Python

Python verfügt über mehrere Funktionen, die Sie direkt von überall in Ihrem Code verwenden können. Diese Funktionen werden als integrierte Funktionen bezeichnet und decken viele gängige Programmierprobleme ab, von mathematischen Berechnungen bis hin zu Python-spezifischen Funktionen.

In diesem Tutorial lernen Sie die Grundlagen der integrierten Funktionen von Python kennen. Am Ende wissen Sie, was ihre Anwendungsfälle sind und wie sie funktionieren. Zum Auftakt beginnen Sie mit den integrierten Funktionen für mathematische Berechnungen.

Verwenden mathematisch relevanter integrierter Funktionen

In Python finden Sie einige integrierte Funktionen, die allgemeine mathematische Operationen durchführen, wie die Berechnung des Absolutwerts einer Zahl, die Berechnung von Potenzen und mehr. Hier ist eine Zusammenfassung der in Python integrierten mathematischen Funktionen:

abs()

Berechnet den absoluten Wert einer Zahl

divmod()

Berechnet den Quotienten und den Rest einer ganzzahligen Division

max()

Sucht das größte der angegebenen Argumente oder Elemente in einer Iterable

min()

Sucht das kleinste der angegebenen Argumente oder Elemente in einer Iterable

pow()

Potenziert eine Zahl

round()

Rundet einen Gleitkommawert

sum()

Summiert die Werte in einer Iterable

In den folgenden Abschnitten erfahren Sie, wie diese Funktionen funktionieren und wie Sie sie in Ihrem Python-Code verwenden.

Den absoluten Wert einer Zahl ermitteln: abs()

Der Absolutwert oder Modul einer reellen Zahl ist ihr nicht negativer Wert. Mit anderen Worten: Der Absolutwert ist die Zahl ohne Vorzeichen. Beispielsweise ist der absolute Wert von -5 5, und der absolute Wert von 5 ist ebenfalls 5.

Mit der in Python integrierten Funktion abs() können Sie schnell den Absolutwert oder Modul einer Zahl berechnen:

>>> from decimal import Decimal
>>> from fractions import Fraction

>>> abs(-42)
42
>>> abs(42)
42

>>> abs(-42.42)
42.42
>>> abs(42.42)
42.42

>>> abs(complex("-2+3j"))
3.605551275463989
>>> abs(complex("2+3j"))
3.605551275463989

>>> abs(Fraction("-1/2"))
Fraction(1, 2)
>>> abs(Fraction("1/2"))
Fraction(1, 2)

>>> abs(Decimal("-0.5"))
Decimal('0.5')
>>> abs(Decimal("0.5"))
Decimal('0.5')

In diesen Beispielen berechnen Sie den absoluten Wert verschiedener numerischer Typen mithilfe der Funktion abs(). Zuerst verwenden Sie ganze Zahlen, dann Gleitkommazahlen und komplexe Zahlen und schließlich Bruch- und Dezimalzahlen. Wenn Sie die Funktion mit einem negativen Wert aufrufen, wird in allen Fällen das Vorzeichen im Endergebnis entfernt.

Nehmen wir als praktisches Beispiel an, dass Sie die Gesamtgewinne und -verluste Ihres Unternehmens aus den Transaktionen eines Monats berechnen müssen:

>>> transactions = [-200, 300, -100, 500]

>>> incomes = sum(income for income in transactions if income > 0)
>>> expenses = abs(
...     sum(expense for expense in transactions if expense < 0)
... )

>>> print(f"Total incomes: ${incomes}")
Total incomes: $800
>>> print(f"Total expenses: ${expenses}")
Total expenses: $300
>>> print(f"Total profit: ${incomes - expenses}")
Total profit: $500

In diesem Beispiel verwenden Sie zur Berechnung der Ausgaben die Funktion abs(), um den absoluten Wert der Ausgaben zu ermitteln, was zu einem positiven Wert führt.

Ermitteln des Quotienten und des Rests bei der Division: divmod()

Python bietet eine integrierte Funktion namens divmod(), die zwei Zahlen als Argumente verwendet und ein Tupel mit dem daraus resultierenden Quotienten und Rest zurückgibt die ganzzahlige Division der eingegebenen Zahlen:

>>> divmod(8, 4)
(2, 0)

>>> divmod(6.5, 3.5)
(1.0, 3.0)

Mit ganzen Zahlen als Argumenten ist das Ergebnis dasselbe wie (a/b, a % b). Bei Gleitkommazahlen ist das Ergebnis (q, a % b), wobei q normalerweise math.floor(a/b) ist , kann aber 1 kleiner sein.

Ein praktisches Beispiel für die Verwendung dieser Funktion: Angenommen, Sie möchten eine Funktion codieren, die einen Zeitwert in Millisekunden annimmt und eine Zeichenfolge im Format "00:00:00" zurückgibt. Hier ist eine mögliche Implementierung mit der Funktion divmod():

>>> def hh_mm_ss(milliseconds):
...     seconds = round(milliseconds / 1000)
...     minutes, seconds = divmod(seconds, 60)
...     hours, minutes = divmod(minutes, 60)
...     return f"{hours:02d}:{minutes:02d}:{seconds:02d}"
...

>>> hh_mm_ss(10000)
'00:00:10'
>>> hh_mm_ss(68000)
'00:01:08'
>>> hh_mm_ss(3680000)
'01:01:20'

In dieser Funktion konvertieren Sie zunächst die eingegebenen Millisekunden in Sekunden und runden das Ergebnis auf die nächste ganze Zahl.

Dann verwenden Sie divmod(), um die Gesamtzahl der Sekunden durch 60 zu dividieren, da eine Minute 60 Sekunden hat. Diese Berechnung ergibt die Minuten und die verbleibenden Sekunden. Schließlich verwenden Sie erneut divmod(), um die Minuten durch 60 zu dividieren, da eine Stunde 60 Minuten hat. Dieses Mal erhalten Sie die Stunden und die verbleibenden Minuten.

Minimale und maximale Werte finden: min() und max()

Manchmal müssen Sie die kleinsten und größten Werte in einer Iteration oder einer Reihe von Werten finden. Dies können allgemeine Berechnungen in der Programmierung sein, und Python verfügt über integrierte Funktionen dafür.

Mit der Funktion min() können Sie den Mindestwert in einer Iterable ermitteln, während Sie mit der Funktion max() den Maximalwert ermitteln können. Hier ist die Signatur beider Funktionen:

min(iterable, *[, default, key])
max(iterable, *[, default, key])

Beide Funktionen nehmen ein erforderliches Argument namens iterable entgegen und geben den Minimal- bzw. Maximalwert zurück. Sie akzeptieren außerdem zwei optionale Nur-Schlüsselwort-Argumente:

default

Kann den Wert enthalten, den Sie zurückgeben möchten, wenn die iterierbare Eingabe leer ist

key

Akzeptiert eine Funktion mit einem Argument, um die Vergleichskriterien anzupassen

Hier sind einige kurze Beispiele für die Verwendung der Funktionen min() und max() mit unterschiedlichen Argumentsätzen:

>>> min([1, 2, 3, 4])
1
>>> max([1, 2, 3, 4])
4

>>> min(1, 2, 3, 4)
1
>>> max(1, 2, 3, 4)
4

>>> min([], default=0)
0
>>> max([], default=0)
0

>>> min([-2, 3, 4, -5, 1], key=abs)
1
>>> max([-2, 3, 4, -5, 1], key=abs)
-5

In den ersten beiden Beispielen verwenden Sie min() und max() mit einer Liste von Zahlen. Sie können diese Funktionen auch mit einer Reihe von Positionsargumenten verwenden.

Dann haben Sie zwei Beispiele für die Verwendung des Arguments default, um einen geeigneten Wert zurückzugeben, wenn die iterierbare Eingabedatei leer ist. Schließlich haben Sie zwei Beispiele für die Verwendung des Arguments key. In diesen Beispielen verwenden Sie die Funktion abs(), um die Vergleichskriterien bereitzustellen.

Rechenleistung: pow()

Wenn Sie Potenzen in Ihrem Code berechnen müssen, können Sie die integrierte Funktion pow() verwenden. Diese Funktion nimmt eine Zahl und erhöht sie auf eine bestimmte Potenz. Hier ist die Signatur der Funktion:

pow(base, exp[, mod=None])

Wenn Sie pow() aufrufen, erhalten Sie base hoch exp. Mit diesen beiden Argumenten entspricht pow() etwas wie base**exp:

>>> pow(2, 8)
256

>>> 2**8
256

Diese Operation berechnet 2 hoch 8, also 256. Dies entspricht einer Potenzoperation mit dem Operator **, den Sie in realem Code häufiger finden.

Mit dem Argument mod können Sie so etwas wie pow(base, exp) % mod tun, aber effizienter berechnen:

>>> import timeit

>>> base = 2
>>> exp = 1000000
>>> mod = 1000000

>>> timeit.timeit(
...     "pow(base, exp, mod)", globals=globals(), number=10
... ) * 1000
0.021042011212557554

>>> timeit.timeit(
...     "pow(base, exp) % mod", globals=globals(), number=10
... ) * 1000
61.956208024639636

In diesem Beispiel verwenden Sie die Funktion timeit() aus dem Modul timeit, um die Rechengeschwindigkeit zu messen. Anschließend definieren Sie einige Variablen für die Berechnung. Beim ersten Aufruf von timeit() verwenden Sie das Argument mod. Im zweiten Aufruf verwenden Sie den Modulo-Operator (%).

Wenn Sie den resultierenden Zeitverbrauch vergleichen, können Sie daraus schließen, dass die Verwendung des mod-Arguments viel schneller ist als die Berechnung der Leistung und die anschließende Anwendung des Modulo-Operators wie in pow(base, exp) % mod.

Zahlen runden: round()

Die in Python integrierte Funktion round() nimmt ein numerisches Argument und gibt es gerundet auf eine bestimmte Anzahl von Ziffern zurück.

Die Signatur von round() wird im folgenden Code angezeigt:

round(number[, ndigits])

In dieser Signatur ist number normalerweise eine Gleitkommazahl, während ndigits ein optionales Argument ist, das eine Ganzzahl sein sollte. Dieses letztere Argument definiert die Genauigkeit oder Anzahl der Nachkommastellen.

Hier ein paar Beispiele:

>>> from math import pi
>>> pi
3.141592653589793

>>> round(pi, 2)
3.14

>>> round(pi, 4)
3.1416

>>> round(pi, 6)
3.141593

In diesen Beispielen verwenden Sie die Konstante pi aus dem Mathematikmodul und die Funktion round(), um die Zahl mit unterschiedlicher Genauigkeit auszudrücken.

Wenn Sie round() mit einem einzelnen Argument verwenden, erhalten Sie möglicherweise überraschende Ergebnisse:

>>> round(1.5)
2

>>> round(2.5)
2

In diesen beiden Beispielen rundet die Funktion round() 1.5 auf 2 und 2.5 auf ab 2. Dies liegt daran, dass round() auf das nächste Vielfache von 10 hoch minus ndigits rundet. Wenn zwei Vielfache gleich nahe beieinander liegen, wird auf die gerade Auswahl gerundet. Diese Halb-auf-Gerade-Rundungsstrategie trägt dazu bei, Rundungsverzerrungen zu verringern. Deshalb rundet 2.5 auf 2 und nicht auf 3.

Gesamtsummen berechnen: sum()

Die in Python integrierte Funktion sum() bietet eine effiziente und pythonische Möglichkeit, eine Liste numerischer Werte zu summieren, was auch ein häufiger Zwischenschritt in vielen Berechnungen ist. sum() ist also ein ziemlich praktisches Werkzeug für einen Python-Programmierer.

Mit der Funktion sum() können Sie eine Reihe von Werten addieren. Seine Signatur sieht wie folgt aus:

sum(iterable[, start=0])

Sie können sum() mit den folgenden zwei Argumenten aufrufen:

iterable

Ein erforderliches Argument, das jedes Python-Iterable enthalten kann.

start

Ein optionales Argument, das einen Anfangswert enthalten kann.

Wenn Sie sum() aufrufen, fügt die Funktion intern start plus die Werte in iterable hinzu. Die Elemente in der Eingabe iterable sind normalerweise numerische Werte. Sie können jedoch auch Listen oder Tupel verwenden. Das start-Argument kann eine Zahl, eine Liste oder ein Tupel akzeptieren, je nachdem, was Ihr iterable enthält.

Hier sind einige Beispiele für die Verwendung von sum() mit verschiedenen Eingaben:

>>> sum([])
0

>>> sum([1, 2, 3, 4, 5])
15

>>> sum([1, 2, 3, 4, 5], 100)  # As a positional argument
115

>>> sum([1, 2, 3, 4, 5], start=100)  # As a keyword argument
115

>>> num_lists = [[1, 2, 3], [4, 5, 6]]
>>> sum(num_lists, start=[])
[1, 2, 3, 4, 5, 6]

>>> num_tuples = ((1, 2, 3), (4, 5, 6))
>>> sum(num_tuples, start=())
(1, 2, 3, 4, 5, 6)

Wenn Sie sum() mit einem leeren Iterable aufrufen, erhalten Sie als Ergebnis 0, da dies der Standardwert von start ist. Der Aufruf der Funktion mit einer Werteliste gibt die Gesamtsumme der bereitgestellten Werte zurück.

Wenn Sie einen anderen start-Wert als 0 verwenden möchten, können Sie ihn als Positions- oder Schlüsselwortargument angeben. Der letztere Ansatz ist jedoch besser lesbar.

Die letzten beiden Beispiele zeigen, dass Sie sum() auch zum Verketten von Listen und Tupeln verwenden können. Beachten Sie, dass Sie start auf das entsprechende Objekt setzen müssen, damit dieser Trick funktioniert. Wenn Sie Listen verketten möchten, muss start eine Liste enthalten und so weiter. Auch wenn dieser Trick funktioniert, ist die Vorgehensweise weder effizient noch üblich. Stattdessen sollten Sie für reguläre Verkettungen den Plus-Operator (+) verwenden.

Ein klassisches Beispiel für die Verwendung von sum() ist die Berechnung des Mittelwerts oder Durchschnitts mehrerer numerischer Werte. In dieser Situation müssen Sie als Zwischenschritt die Eingabedaten summieren. Hier ist ein Beispiel:

def mean(values):
    try:
        return sum(values) / len(values)
    except ZeroDivisionError:
        raise ValueError("mean() arg shouldn't be empty") from None

In dieser mean()-Funktion verwenden Sie sum(), um die Eingabewerte zu summieren und dann das Ergebnis durch die Anzahl der Werte in den Eingabedaten zu dividieren.

Erstellen und Bearbeiten grundlegender Datentypen

Python verfügt über mehrere integrierte Funktionen, mit denen Sie grundlegende Datentypen wie Ganzzahlen und Gleitkommazahlen, Zeichenfolgen und boolesche Werte bearbeiten können. Hier ist eine Zusammenfassung der integrierten Funktionen, die Ihnen bei der Verarbeitung grundlegender Datentypen helfen:

int()

Konstruiert ein ganzzahliges Objekt aus einer Zahl oder einem String

bin()

Konvertiert eine Ganzzahl in eine Binärzeichenfolge

oct()

Konvertiert eine Ganzzahl in eine Oktalzeichenfolge

hex()

Konvertiert eine Ganzzahl in eine hexadezimale Zeichenfolge

float()

Konstruiert ein Gleitkommaobjekt aus einer Zahl oder einem String

complex()

Konstruiert eine komplexe Zahl aus Argumenten

str()

Erstellt ein String-Objekt

repr()

Erstellt eine entwicklerfreundliche Zeichenfolgendarstellung eines Objekts

bool()

Konvertiert ein Argument in einen booleschen Wert

ord()

Sucht nach dem ganzzahligen Codepunkt eines Zeichens

chr()

Sucht nach dem Zeichen für den angegebenen ganzzahligen Codepunkt

bytes()

Erstellt ein bytes-Objekt (ähnlich wie bytearray, aber unveränderlich)

bytearray()

Erstellt ein Objekt der Klasse bytearray

In den folgenden Abschnitten lernen Sie die Grundlagen der Arbeit mit diesen Funktionen und wie Sie sie in Ihrem Python-Code verwenden.

Darstellung ganzer Zahlen: int(), bin(), oct() und hex()

Ganzzahlen sind beim Programmieren sehr nützlich. Python verfügt über einen integrierten Datentyp namens int, der ganze Zahlen darstellt. Wenn Sie mit ganzen Zahlen arbeiten, müssen Sie diese manchmal in verschiedenen Basen wie 2, 8 oder 16 ausdrücken. Möglicherweise müssen Sie auch Zeichenfolgen oder andere numerische Typen in Ganzzahlen konvertieren.

Für die letztere Aufgabe können Sie die integrierte Funktion int() verwenden. Hier sind einige Beispiele für die Verwendung:

>>> int()
0

>>> int(42.42)
42

>>> int("42")
42

>>> int("42.42")
Traceback (most recent call last):
    ...
ValueError: invalid literal for int() with base 10: '42.42'

>>> int("one")
Traceback (most recent call last):
    ...
ValueError: invalid literal for int() with base 10: 'one'

Ohne Argument gibt int() 0 zurück. Dieses Verhalten ist besonders nützlich, wenn Sie eine Factory-Funktion für Klassen wie defaultdict aus dem Modul collections benötigen. Bei Gleitkommazahlen entfernt int() lediglich den Dezimalteil und gibt den gesamten Teil zurück. Schließlich gibt int() mit einer Zeichenfolge als Argument nur dann die entsprechende Ganzzahl zurück, wenn die Zeichenfolge eine gültige Ganzzahl darstellt.

Sie können auch int() verwenden, um eine binäre, oktale oder hexadezimale Zeichenfolgendarstellung in eine Ganzzahl umzuwandeln:

>>> int("0b10", base=2)
2

>>> int("0o10", base=8)
8

>>> int("0x10", base=16)
16

Im ersten Beispiel verwenden Sie int(), um eine Zeichenfolge, die eine Zahl im Binärformat darstellt, in die entsprechende dezimale Ganzzahl umzuwandeln. Beachten Sie, dass Sie das Argument base auf die entsprechende Basis setzen müssen, damit dieser Vorgang funktioniert, also 2 für Binärzahlen. Als Nächstes führen Sie ähnliche Konvertierungen mit oktalen und hexadezimalen Zeichenfolgen durch. Auch hier müssen Sie base auf den entsprechenden Wert setzen.

Mit den Funktionen bin(), oct() und hex() können Sie den umgekehrten Vorgang ausführen. Mit ihnen können Sie eine bestimmte Ganzzahl in ihre binäre, oktale oder hexadezimale Darstellung umwandeln:

>>> bin(42)
'0b101010'

>>> oct(42)
'0o52'

>>> hex(42)
'0x2a'

In diesen Beispielen verwenden Sie eine Ganzzahl als Argument für bin(), oct() und hex(). Als Ergebnis erhalten Sie die Zeichenfolgendarstellung des Eingabewerts im Binär-, Oktal- bzw. Hexadezimalformat.

Andere Zahlen manipulieren: float() und complex()

Python verfügt über grundlegende integrierte Typen zur Darstellung von Gleitkommazahlen und komplexen Zahlen. Diese Typen verfügen über zugehörige integrierte Funktionen für Konvertierungszwecke. Für Gleitkommazahlen gibt es also die Funktion float() und für komplexe Zahlen die Funktion complex().

Hier sind die Signaturen beider Funktionen:

float(number=0.0)

complex(real=0, imag=0)
complex(string)

Die Funktion float() akzeptiert ein einzelnes Argument, das einen numerischen Wert darstellt. Dieses Argument akzeptiert Zahlen oder Zeichenfolgen, die gültige Zahlen darstellen:

>>> float()
0.0

>>> float(42)
42.0

>>> float("42")
42.0

>>> float("3.14")
3.14

>>> float("one")
Traceback (most recent call last):
    ...
ValueError: could not convert string to float: 'one'

Ohne Argumente gibt float() 0.0 zurück. Bei Ganzzahlen wird die entsprechende Gleitkommazahl mit 0 als Dezimalteil zurückgegeben. Bei Zeichenfolgen, die Zahlen darstellen, gibt float() die entsprechende Gleitkommazahl zurück. Dies schlägt jedoch fehl, wenn die Eingabezeichenfolge keinen gültigen numerischen Wert darstellt.

Mit der Funktion complex() können Sie mit komplexen Zahlen arbeiten. Diese Funktion hat zwei verschiedene Signaturen. Die erste Signatur hat zwei Argumente:

real

Der Realteil der Zahl

imag

Der Imaginärteil der Zahl

Diese Argumente akzeptieren numerische Werte wie Ganzzahlen oder Gleitkommazahlen. So funktioniert diese Variante von complex():

>>> complex(3, 6)
(3+6j)

>>> complex(1, 0)
(1+0j)

>>> complex(0, 1)
1j

>>> complex(3.14, -2.75)
(3.14-2.75j)

Sie können complex() mit numerischen Werten aufrufen, was zu einer komplexen Zahl führt. Beachten Sie, dass Python ein j verwendet, um den Imaginärteil zu definieren.

Die zweite Signatur von complex() benötigt ein einzelnes Argument, das ein String sein sollte:

>>> complex("3+6j")
(3+6j)

>>> complex("1+0j")
(1+0j)

>>> complex("1j")
1j

>>> complex("3.14-2.75j")
(3.14-2.75j)

Wenn Sie Zeichenfolgen zum Erstellen komplexer Zahlen mit complex() verwenden, müssen Sie sicherstellen, dass die Eingabezeichenfolge ein gültiges Format hat. Es sollte aus dem Realteil, dem Vorzeichen und dem Imaginärteil bestehen. Sie können keine Leerzeichen hinzufügen, um diese Komponenten zu trennen.

Strings erstellen und darstellen: str() und repr()

Beim Erstellen und Arbeiten mit Python-Strings müssen Sie zwei grundlegende integrierte Funktionen berücksichtigen:

    str()
    repr()

Mit der Funktion str() können Sie neue Strings erstellen oder bestehende Objekte in Strings konvertieren:

>>> str()
''

>>> str(42)
'42'

>>> str(3.14)
'3.14'

>>> str([1, 2, 3])
'[1, 2, 3]'

>>> str({"one": 1, "two": 2, "three": 3})
"{'one': 1, 'two': 2, 'three': 3}"

>>> str({"A", "B", "C"})
"{'B', 'C', 'A'}"

Im ersten Beispiel verwenden Sie str() ohne Argument, um eine leere Zeichenfolge zu erstellen. In den anderen Beispielen erhalten Sie Strings mit benutzerfreundlichen Darstellungen der Eingabeobjekte.

Nehmen wir für einen praktischen Anwendungsfall an, dass Sie eine Liste numerischer Werte haben und diese mit der Methode str.join() verknüpfen möchten, die nur iterierbare Zeichenfolgen akzeptiert. In diesem Fall können Sie etwa Folgendes tun:

>>> "-".join(str(value) for value in [1, 2, 3, 4, 5])
'1-2-3-4-5'

In diesem Beispiel verwenden Sie einen Generatorausdruck, um jede Zahl in ihre Zeichenfolgendarstellung umzuwandeln, bevor Sie .join() aufrufen. Auf diese Weise vermeiden Sie einen Fehler in Ihrem Code.

Die integrierte Funktion repr() wiederum liefert Ihnen eine entwicklerfreundliche Darstellung des jeweiligen Objekts:

>>> repr(42)
'42'

>>> repr(3.14)
'3.14'

>>> repr([1, 2, 3])
'[1, 2, 3]'

>>> repr({"one": 1, "two": 2, "three": 3})
"{'one': 1, 'two': 2, 'three': 3}"

>>> repr({"A", "B", "C"})
"{'B', 'C', 'A'}"

Bei integrierten Typen ist die Zeichenfolgendarstellung, die Sie mit repr() erhalten, dieselbe wie die, die Sie mit der Funktion str() erhalten.

Um den Unterschied zwischen str() und repr() zu sehen, betrachten Sie das folgende Beispiel, das das Modul datetime verwendet:

>>> import datetime
>>> today = datetime.datetime.now()

>>> repr(today)
'datetime.datetime(2024, 7, 1, 12, 38, 53, 180208)'

>>> str(today)
'2024-07-01 12:38:53.180208'

Die repr()-Methode bietet Ihnen eine entwicklerfreundliche String-Darstellung des datetime-Objekts. Idealerweise sollten Sie das Objekt mithilfe dieser Darstellung neu erstellen können. Mit anderen Worten: Sie sollten in der Lage sein, die resultierende Darstellung zu kopieren und einzufügen, um das Objekt neu zu erstellen. Aus diesem Grund gilt diese String-Darstellung als entwicklerfreundlich.

Im Gegensatz dazu sollte die Zeichenfolgendarstellung, die Sie durch den Aufruf von str() erhalten, darauf abzielen, für Endbenutzer lesbar und informativ zu sein.

Boolesche Werte verarbeiten: bool()

Mit der in Python integrierten Funktion bool() können Sie den Wahrheitswert jedes Python-Objekts bestimmen. Es handelt sich um eine Prädikatfunktion, da sie immer True oder False zurückgibt. Um herauszufinden, ob ein Objekt falsch ist, d. h. ob bool() bei Anwendung auf das Objekt False zurückgibt, verwendet Python Folgendes Interne Regeln:

  • Konstanten, die als falsch definiert sind: None und False
  • Die Null eines beliebigen numerischen Typs: 0, 0.0, 0j, Decimal(0), Fraction (0, 1)
  • Leere Sequenzen und Sammlungen: '', (), [], {}, set( ), range(0)

Der Rest der Objekte gilt in Python als wahr. Benutzerdefinierte Objekte gelten standardmäßig als wahr, es sei denn, sie stellen eine spezielle Methode .__bool__() bereit, die ein anderes Verhalten definiert.

Hier sind einige Beispiele für die Funktionsweise von bool():

>>> bool()
False

>>> bool(0)
False
>>> bool(42)
True

>>> bool(0.0)
False
>>> bool(3.14)
True

>>> bool("")
False
>>> bool("Hello")
True

>>> bool([])
False
>>> bool([1, 2, 3])
True

Im ersten Beispiel rufen Sie bool() ohne Argument auf und erhalten als Ergebnis False. In den restlichen Beispielen können Sie bestätigen, dass Python die oben aufgeführten Regeln konsequent anwendet. In der Praxis müssen Sie bool() nur verwenden, wenn Ihr Code explizit einen booleschen Wert anstelle eines anderen Objekts erfordert.

Nehmen wir als Beispiel für die Verwendung von bool() an, dass Sie die folgende Implementierung einer Stapeldatenstruktur haben:

class Stack:
    def __init__(self, items=None):
        self.items = list(items) if items is not None else []

    def push(self, item):
        self.items.append(item)

    def pop(self):
        return self.items.pop()

    def __bool__(self):
        return bool(self.items)

In diesem Beispiel implementiert Ihre Stack-Klasse die spezielle Methode .__bool__(), um boolesche Operationen für ihre Objekte zu unterstützen. Diese Methode garantiert, dass die Funktion bool() False und andernfalls True zurückgibt, wenn ein bestimmtes Stack-Objekt leer ist . Hier ist ein Beispiel:

>>> from stack import Stack

>>> stack = Stack()

>>> bool(stack)
False

>>> stack.push(4)

>>> bool(stack)
True

In diesem Codeausschnitt erstellen Sie zunächst einen leeren Stapel. Wenn Sie dieses Objekt an bool() übergeben, erhalten Sie False. Anschließend verschieben Sie einen Wert in den Stapel und rufen erneut bool() auf. Dieses Mal erhalten Sie True, da der Stapel nicht mehr leer ist.

Codierungszeichenfolgen: ord() und chr()

Die Zeichenkodierung ist in den meisten Programmiersprachen ein wichtiges Thema. In Python verwenden Zeichenfolgen die standardmäßig festgelegten Unicode-Zeichen. Jedem Unicode-Zeichen ist ein Codepunkt zugeordnet, bei dem es sich um eine Ganzzahl handelt. Um den Codepunkt eines bestimmten Zeichens zu erhalten, können Sie die integrierte Funktion ord() verwenden:

>>> ord("A")
65

>>> ord("Z")
90

>>> ord("x")
120

>>> ord("ñ")
241

>>> ord("&")
38

Jedem Unicode-Zeichen ist ein Codepunkt zugeordnet, der das Zeichen in der Unicode-Tabelle eindeutig identifiziert. In diesen Beispielen verwenden Sie die Funktion, um den Codepunkt einiger Zeichen abzurufen.

In der Praxis können Sie die Funktion ord() verwenden, um grundlegende kryptografische Techniken zu implementieren, Zeichenfolgen oder Zeichen zu sortieren, Eingabezeichen zu validieren usw. Hier ist ein kurzes Spielzeugbeispiel für eine Funktion, die nur prüft, ob alle Zeichen in einer Zeichenfolge Großbuchstaben des englischen Alphabets sind:

>>> def is_uppercase(text):
...     for char in text:
...         if not (65 <= ord(char) <= 90):
...             return False
...     return True
...

>>> is_uppercase("HELLO")
True

>>> is_uppercase("Hello")
False

In dieser Funktion verwenden Sie ord(), um zu bestimmen, ob die Zeichen in einer Zeichenfolge zwischen 65 und 90 liegen, was dem Codeintervall entspricht Punkte für Großbuchstaben A bis Z in der Unicode-Tabelle.

Manchmal müssen Sie möglicherweise den Codepunkt bestimmen, der ein bestimmtes Unicode-Zeichen identifiziert. In dieser Situation können Sie die integrierte Funktion chr() verwenden:

>>> chr(65)
'A'

>>> chr(90)
'Z'

>>> chr(120)
'x'

>>> chr(241)
'ñ'

>>> chr(38)
'&'

Die Funktion chr() führt die entgegengesetzte Operation von ord() aus. Damit können Sie den Codepunkt finden, der einem bestimmten Zeichen zugeordnet ist.

Die Funktionen ord() und chr() ergänzen sich gewissermaßen und werden daher wahrscheinlich gemeinsam verwendet.

Erstellen von Bytes und Bytearrays: bytes() und bytearray()

Pythons Bytes und Byte-Arrays sind integrierte Typen, die Python sofort bereitstellt, um Binärdaten zu bearbeiten, Text zu kodieren und zu dekodieren, Dateieingaben und -ausgaben zu verarbeiten und über Netzwerke zu kommunizieren.

Der Datentyp bytes ist unveränderlich, während der Typ bytearray veränderbar ist. Um von diesen Datentypen abgeleitete Objekte zu erstellen, können Sie die integrierten Funktionen bytes() und bytearray() verwenden.

Die Funktionen bytes() und bytearray() haben die folgenden Signaturen:

bytes(source=b"")
bytes(source, encoding)
bytes(source, encoding, errors)

bytearray(source=b"")
bytearray(source, encoding)
bytearray(source, encoding, errors)

Beide Funktionen haben drei unterschiedliche Signaturen. Die erste Signatur beider Funktionen akzeptiert ein bytes-Literal als Argument. Diese Literale ähneln String-Literalen, beginnen jedoch mit einem b und akzeptieren nur ASCII-Zeichen.

Hier ist eine Zusammenfassung der Argumente und ihrer Bedeutung:

source

Ein bytes-Literal oder eine Zeichenfolge

encoding

Die Zeichenkodierung, die zum Dekodieren von source verwendet werden soll, wenn sie eine Zeichenfolge enthält

errors

Ein Handler für Codierungs- und Decodierungsfehler

Das Argument encoding ist nur erforderlich, wenn das Argument source eine Zeichenfolge ist. In diesem Fall müssen Sie die entsprechende Codierung angeben, damit Python die Zeichenfolge in Bytes konvertieren kann.

Schließlich sind die errors-Argumente ebenfalls optional und sollten einen der folgenden Fehlerhandler enthalten:

"strict"

Löst eine UnicodeDecodeError- oder UnicodeEncodeError-Ausnahme aus, wenn Kodierungsprobleme auftreten

"ignore"

Ignoriert die Zeichen, die nicht codiert werden können

"replace"

Ersetzt die Zeichen, die nicht kodiert werden können, durch ein Fragezeichen (?)

"xmlcharrefreplace"

Ersetzt die Zeichen, die nicht codiert werden können, durch eine XML-Zeichenreferenz

"backslashreplace"

Ersetzt die Zeichen, die nicht codiert werden können, durch die String-Backslash-Escape-Sequenzen von Python

Durch die Auswahl der geeigneten Fehlerhandler können Sie eine gute Strategie für Situationen festlegen, in denen Sie die Funktionen bytes() und bytearray() mit fehlerhaften Daten aufrufen.

Hier sind einige Beispiele für die Verwendung der Funktionen bytes() und bytearray():

>>> bytes()
b''

>>> bytes(b"Using ASCII characters or bytes \xc3\xb1")
b'Using ASCII characters or bytes \xc3\xb1'

>>> bytes("Using non-ASCII characters: ñ Ł", encoding="utf-8")
b'Using non-ASCII characters: \xc3\xb1 \xc5\x81'

>>> bytearray()
bytearray(b'')

>>> bytearray(b"Using ASCII characters or bytes \xc3\xb1")
bytearray(b'Using ASCII characters or bytes \xc3\xb1')

>>> bytearray("Using non-ASCII characters: ñ Ł", encoding="utf-8")
bytearray(b'Using non-ASCII characters: \xc3\xb1 \xc5\x81')

In diesen Beispielen erstellen Sie bytes- und bytearray-Objekte mit bytes-Literalen und Zeichenfolgen mit der richtigen Codierung als Argument. Beachten Sie, dass Sie die Funktion bytes() ohne Argumente aufrufen können, um ein leeres bytes-Objekt zu erstellen.

Betrachten Sie nun die folgenden Beispiele, die zeigen, wie Fehlerhandler verwendet werden:

>>> bytes(
...     "Using non-ASCII characters with the ASCII encoding: ñ Ł",
...     encoding="ascii"
... )
Traceback (most recent call last):
    ...
UnicodeEncodeError: 'ascii' codec can't encode character '\xf1'
    in position 52: ordinal not in range(128)

>>> bytes(
...     "Using non-ASCII characters with the ASCII encoding: ñ Ł",
...     encoding="ascii",
...     errors="ignore"
... )
b'Using non-ASCII characters with the ASCII encoding:  '

>>> bytes(
...     "Using non-ASCII characters with the ASCII encoding: ñ Ł",
...     encoding="ascii",
...     errors="replace"
... )
b'Using non-ASCII characters with the ASCII encoding: ? ?'

>>> bytes(
...     "Using non-ASCII characters with the ASCII encoding: ñ Ł",
...     encoding="ascii",
...     errors="xmlcharrefreplace"
... )
b'Using non-ASCII characters with the ASCII encoding: &#241; &#321;'

>>> bytes(
...     "Using non-ASCII characters with the ASCII encoding: ñ Ł",
...     encoding="ascii",
...     errors="backslashreplace"
... )
b'Using non-ASCII characters with the ASCII encoding: \\xf1 \\u0141'

In diesen Beispielen verwenden Sie nur bytes(), da bytearray() ähnlich funktionieren würde. Der einzige Unterschied besteht darin, dass bytes() unveränderliche Objekte zurückgibt, während bytearray() veränderliche Objekte zurückgibt.

In diesen Beispielen werden Nicht-ASCII-Zeichen mit der ASCII-Codierung verwendet, was zu Codierungsfehlern führt, die Sie beheben müssen. Der Standardwert des Arguments errors ist "strict". Aus diesem Grund erhalten Sie im ersten Beispiel oben eine UnicodeEncodeError-Ausnahme.

Dann setzen Sie errors auf "ignore", damit Python alle Codierungsfehler ignoriert. In diesem Fall werden die Zeichen ñ und Ł entfernt. Wenn Sie errors auf "replace" setzen, werden ñ und Ł jeweils durch ein Fragezeichen ersetzt.

Durch die Verwendung von "xmlcharrefreplace" als Fehlerhandler ersetzt Python die Zeichen ñ und Ł durch ihre jeweilige XML-Zeichenreferenz. Schließlich werden durch die Verwendung von "backslashreplace" die problematischen Zeichen mithilfe der entsprechenden Escape-Sequenz maskiert.

Sammlungsdatentypen erstellen

Ein grundlegendes Merkmal von Python ist der umfangreiche Satz an Sammlungsdatentypen, die in die Sprache integriert sind. Sie verfügen über mehrere integrierte Funktionen, mit denen Sie diese Datentypen bearbeiten können, darunter Listen, Tupel, Wörterbücher, Mengen und Bytes.

Hier ist eine Zusammenfassung der integrierten Funktionen, die Sie bei der Verarbeitung von Sammlungsdatentypen unterstützen:

list()

Erstellt ein list-Objekt aus einem iterierbaren Objekt

tuple()

Erstellt ein tuple-Objekt aus einem iterierbaren Objekt

dict()

Erstellt ein dict-Objekt aus einer Reihe von Schlüssel-Wert-Paaren oder Schlüsselwortargumenten

set()

Erstellt ein set-Objekt aus einem iterierbaren Objekt

frozenset()

Erstellt ein frozenset-Objekt aus einem iterierbaren Objekt

In den folgenden Abschnitten lernen Sie die Grundlagen der Arbeit mit diesen Funktionen und deren Verwendung zum Erstellen und Bearbeiten von Sammlungen in Ihrem Python-Code.

Erstellen von Listen und Tupeln: list() und tuple()

Pythons list ist ein grundlegender integrierter Datentyp mit einer beeindruckenden Reihe von Funktionen. Listen sind veränderbar und ermöglichen Ihnen die effiziente Organisation und Bearbeitung von Daten, die heterogen sein können, in der Regel aber homogen sind. Sie können beispielsweise eine Liste verwenden, um eine Spalte aus einer Datenbanktabelle zu speichern.

Ebenso ist Pythons tuple ein weiterer integrierter Typ. Im Gegensatz zu Listen sind Tupel unveränderlich. Sie können sie verwenden, um Daten zu organisieren, die zwar homogen, aber typischerweise heterogen sind. Sie können beispielsweise ein Tupel verwenden, um eine Zeile aus einer Datenbanktabelle zu speichern.

Mit den in Python integrierten Funktionen list() und tuple() können Sie list- und tuple-Objekte erstellen.

Die Funktion list() verwendet ein Iterable als Argument und gibt ein aus den Eingabedaten erstelltes list-Objekt zurück. Seine Signatur sieht also etwa so aus:

list([iterable])

Beachten Sie, dass die eckigen Klammern um iterable bedeuten, dass das Argument optional ist, sodass die Klammern nicht Teil der Syntax sind.

Hier sind einige Beispiele für die Verwendung von list() zum Erstellen von list-Objekten:

>>> list()
[]

>>> list("Hello")
['H', 'e', 'l', 'l', 'o']

>>> list((1, 2, 3, 4, 5))
[1, 2, 3, 4, 5]

>>> list({"circle", "square", "triangle", "rectangle", "pentagon"})
['square', 'rectangle', 'triangle', 'pentagon', 'circle']

>>> list({"name": "John", "age": 30, "city": "New York"})
['name', 'age', 'city']
>>> list({"name": "John", "age": 30, "city": "New York"}.keys())
['name', 'age', 'city']

>>> list({"name": "John", "age": 30, "city": "New York"}.values())
['John', 30, 'New York']

>>> list({"name": "John", "age": 30, "city": "New York"}.items())
[('name', 'John'), ('age', 30), ('city', 'New York')]

Wenn Sie list() ohne Argument aufrufen, erstellen Sie eine neue leere Liste. Wenn Sie eine Zeichenfolge als Argument verwenden, erstellen Sie eine Liste von Zeichen. Wenn Sie ein Tupel verwenden, konvertieren Sie das Tupel in eine Liste.

Die Funktion list() akzeptiert sogar Mengen, aber Sie müssen bedenken, dass Mengen ungeordnete Datenstrukturen sind, sodass Sie die endgültige Reihenfolge der Elemente in der resultierenden Liste nicht vorhersagen können.

Bei der Verwendung von Wörterbüchern mit list() haben Sie vier Möglichkeiten. Sie können eine Liste von Schlüsseln erstellen, indem Sie direkt das Wörterbuch verwenden oder dessen Methode .keys() verwenden. Wenn Sie eine Werteliste erstellen möchten, können Sie die Methode .values() verwenden. Wenn Sie schließlich eine Liste von Schlüssel-Wert-Paaren erstellen möchten, können Sie die Methode .items() verwenden.

Listen haben viele Anwendungsfälle im Python-Code. Sie sind flexibel, leistungsstark und funktionsreich, sodass Sie sie in fast jedem Teil des Python-Codes finden.

Tupel werden üblicherweise zum Speichern heterogener und unveränderlicher Daten verwendet. Mit der Funktion tuple() können Sie Tupel im Handumdrehen erstellen. Hier ist die Signatur:

tuple([iterable])

Die eckigen Klammern um iterable bedeuten, dass das Argument optional ist, die Klammern also nicht Teil der Syntax sind.

Betrachten Sie die folgenden Beispiele für die Verwendung von tuple() in Ihrem Code:

>>> tuple()
()

>>> tuple("Hello")
('H', 'e', 'l', 'l', 'o')

>>> tuple(["Jane Doe", 25, 1.75, "Canada"])
('Jane Doe', 25, 1.75, 'Canada')

>>> tuple({
...     "manufacturer": "Ford",
...     "model": "Mustang",
...     "color": "Blue",
... }.values())
('Ford', 'Mustang', 'Blue')

Sie können tuple() ohne Argumente verwenden, um ein leeres Tupel zu erstellen. Dies ist besser lesbar als die Verwendung eines leeren Klammerpaars (). Wenn Sie eine Zeichenfolge an tuple() übergeben, erhalten Sie ein Tupel von Zeichen.

Im dritten Beispiel verwenden Sie tuple(), um eine Liste heterogener Daten in ein Tupel umzuwandeln, was eine geeignetere Datenstruktur zum Speichern dieser Art von Daten wäre. Schließlich verwenden Sie die Werte eines Wörterbuchs, um ein Tupel zu erstellen.

Genau wie Listen sind Tupel in Python sehr nützlich. Sie werden sie in vielen Anwendungsfällen sehen, insbesondere in Situationen, in denen Sie unveränderliche heterogene Daten speichern müssen.

Wörterbücher erstellen: dict()

Wörterbücher sind eine grundlegende integrierte Datenstruktur in Python. Sie sind überall und ein zentraler Bestandteil der Sprache selbst. In Ihrem Code finden Sie viele Anwendungsfälle für Wörterbücher. Wie andere integrierte Sammlungen verfügt auch Python über eine integrierte Funktion, mit der Sie Wörterbücher erstellen können: die Funktion dict().

Die Funktion dict() hat die folgenden Signaturen:

dict(**kwargs)
dict(mapping, **kwargs)
dict(iterable, **kwargs)

Alle diese Signaturen akzeptieren sogenannte Schlüsselwortargumente (**kwargs) oder benannte Argumente. Die zweite Signatur übernimmt eine Zuordnung, bei der es sich um ein anderes Wörterbuch handeln kann. Schließlich akzeptiert die dritte Signatur ein iterierbares Schlüssel-Wert-Paar, bei dem es sich beispielsweise um eine Liste von Tupeln mit zwei Elementen handeln kann.

Hier sind einige kurze Beispiele für die unterschiedliche Verwendung der Funktion dict():

>>> dict()
{}

>>> jane = dict(name="Jane", age="30", country="Canada")
>>> jane
{'name': 'Jane', 'age': '30', 'country': 'Canada'}

>>> dict(jane, job="Python Dev")
{'name': 'Jane', 'age': '30', 'country': 'Canada', 'job': 'Python Dev'}

>>> dict([("name", "Jane"), ("age", 30), ("country", "Canada")])
{'name': 'Jane', 'age': 30, 'country': 'Canada'}

Auch hier können Sie beim Erstellen eines leeren Wörterbuchs die Funktion dict() ohne Argumente verwenden. Dies ist weniger üblich als die Verwendung eines Paares geschweifter Klammern {}, kann aber in manchen Kontexten wiederum lesbarer und expliziter sein.

Anschließend erstellen Sie ein jane-Wörterbuch mit Schlüsselwortargumenten. Dies ist eine saubere und elegante Möglichkeit, Wörterbücher in Python zu erstellen.

Das dritte Beispiel zeigt, wie Sie eine Zuordnung mit Schlüsselwortargumenten kombinieren können, um ein neues Wörterbuchobjekt zu erstellen. Schließlich erstellen Sie im vierten Beispiel ein neues Wörterbuch aus einer Liste von Tupeln.

Erstellen von Sets und eingefrorenen Sets: set() und frozenset()

Pythons set ist ein integrierter Datentyp zum Erstellen von Sammlungen eindeutiger und hashbarer Objekte, die normalerweise als Elemente oder Mitglieder bezeichnet werden. In Python unterstützen Mengen die für mathematische Mengen definierten Operationen, einschließlich Vereinigung, Differenz, symmetrische Differenz und andere.

Python hat zwei Arten von Mengen:

    set
    frozenset

Der Unterschied zwischen diesen beiden Datentypen besteht darin, dass set-Objekte veränderbar und frozenset-Objekte unveränderlich sind.

Wie andere Datentypen bietet Python auch integrierte Funktionen zum Erstellen von Mengen und eingefrorenen Mengen. Sie verfügen jeweils über die Funktionen set() und frozenset(). Die Signatur für diese Funktionen ist unten dargestellt:

set([iterable])
frozenset([iterable])

Auch hier zeigen die eckigen Klammern an, dass die Eingabe iterierbar optional ist. Schauen Sie sich nun die folgenden Beispiele zum Erstellen von Sets und eingefrorenen Sets an:

>>> set()
set()

>>> frozenset()
frozenset()

>>> set(["square", "rectangle", "triangle", "pentagon", "circle"])
{'square', 'triangle', 'circle', 'rectangle', 'pentagon'}

>>> frozenset(["square", "rectangle", "triangle", "pentagon", "circle"])
frozenset({'square', 'triangle', 'circle', 'rectangle', 'pentagon'})

>>> set(("red", "green", "blue", "red"))
{'green', 'red', 'blue'}

>>> frozenset(("red", "green", "blue", "red"))
frozenset({'green', 'red', 'blue'})

Wenn Sie set() und frozenset() ohne Argumente aufrufen, erstellen Sie eine leere bzw. eingefrorene Menge. Im Fall von Mengen haben Sie kein Literal, mit dem Sie eine leere Menge erstellen können, da ein Paar geschweifter Klammern ({}) ein leeres Wörterbuch definiert. Um also einen leeren Satz zu erstellen, müssen Sie die Funktion set() verwenden.

In den restlichen Beispielen verwenden Sie iterierbare Elemente wie Listen und Tupel, um Mengen und eingefrorene Mengen zu erstellen. Es ist wichtig zu beachten, dass der endgültige Satz eine einzelne Instanz des wiederholten Elements enthält, wenn die Eingabe-Iterable wiederholte Elemente enthält. Außerdem handelt es sich bei Mengen um ungeordnete Datenstrukturen, sodass Sie bei der Bereitstellung einer Liste die endgültige Reihenfolge der Elemente in der resultierenden Menge nicht vorhersagen können.

Verarbeitung von Iterables und Iteratoren

Die Iteratoren und Iterables von Python sind zwei unterschiedliche, aber verwandte Tools, die nützlich sind, wenn Sie einen Datenstrom oder eine Datensammlung iterieren müssen. Iteratoren steuern und steuern den Iterationsprozess, während Iterables normalerweise Daten enthalten, die jeweils über einen Wert iteriert werden können.

Python verfügt über mehrere integrierte Funktionen, die Sie zum Arbeiten mit Iterables und Iteratoren verwenden können. Hier ist eine Zusammenfassung dieser Funktionen:

len()

Berechnet die Länge eines Objekts mit der richtigen Größe

reversed()

Konstruiert einen umgekehrten Iterator

sorted()

Erstellt eine sortierte Liste aus einer iterierbaren Liste

all()

Überprüft, ob alle Elemente einer Iterable wahr sind

any()

Überprüft, ob Elemente einer Iterable wahr sind

range()

Erzeugt einen Bereich ganzzahliger Werte

enumerate()

Erstellt einen Iterator von Tupeln, die Indizes und Werte aus einem Iterable enthalten

slice()

Erstellt ein slice-Objekt

zip()

Erstellt einen Iterator, der Elemente aus Iterables aggregiert

iter()

Konstruiert ein Iteratorobjekt

next()

Ruft das nächste Element von einem Iterator ab

filter()

Filtert Elemente aus einem iterierbaren Element

map()

Wendet eine Funktion auf jedes Element einer Iterable an

In den folgenden Abschnitten erfahren Sie mehr über all diese integrierten Funktionen und wie sie bei der Verarbeitung von Iterables und Iteratoren in Ihrem Python-Code nützlich sein können.

Bestimmen der Anzahl der Elemente in einem Container: len()

Einer der häufigsten Vorgänge, die Sie an Sammlungen durchführen, besteht darin, die Anzahl der in einer vorhandenen Sequenz oder Sammlung gespeicherten Elemente zu bestimmen. Um diese Aufgabe abzuschließen, verfügt Python über die integrierte Funktion len().

Die Funktion len() akzeptiert ein einzelnes Argument, bei dem es sich um eine Sequenz wie einen String, ein Tupel oder eine Liste handeln kann. Es kann sich auch um eine Sammlung handeln, beispielsweise um ein Wörterbuch, einen Satz oder einen eingefrorenen Satz. Die Funktion gibt die Länge oder Anzahl der Elemente des Eingabeobjekts zurück.

Hier sind einige Beispiele für die Verwendung von len() mit verschiedenen Objekten:

>>> len("Python")
6

>>> len(("Jane Doe", 25, 1.75, "Canada"))
4

>>> len([1, 2, 3, 4, 5])
5

>>> len({"green", "red", "blue"})
3

>>> len({"name": "Jane", "age": 30, "country": "Canada"})
3

Im ersten Beispiel verwenden Sie len(), um die Anzahl der Zeichen in einer Zeichenfolge abzurufen. Anschließend verwenden Sie die Funktion, um die Länge eines Tupels, einer Liste und einer Menge zu bestimmen. Schließlich verwenden Sie len() mit einem Wörterbuch als Argument. In diesem Fall erhalten Sie die Anzahl der Schlüssel-Wert-Paare im Eingabewörterbuch.

Beachten Sie, dass len() 0 zurückgibt, wenn Sie es mit leeren Containern aufrufen:

>>> len("")
0
>>> len(())
0
>>> len([])
0

In diesen Beispielen verwenden Sie len() mit einer leeren Zeichenfolge, einem Tupel und einer Liste. In allen Fällen erhalten Sie als Ergebnis 0.

Die Funktion len() kann in mehreren Situationen nützlich sein. Ein häufiges Beispiel ist die Berechnung des Durchschnitts einer Reihe numerischer Werte:

>>> grades = [90, 97, 100, 87]

>>> sum(grades) / len(grades)
93.5

In diesem Beispiel gibt Ihnen len() die Anzahl der Werte in der Notenliste an. Aus diesem Wert errechnen Sie dann die Durchschnittsnote.

Iterables umkehren und sortieren: reversed() und sorted()

Das Umkehren und Sortieren der Werte in einer Iterable ist ein weiterer nützlicher Vorgang in der Programmierung. Da diese Operationen so häufig vorkommen, verfügt Python über integrierte Funktionen dafür. Wenn Sie eine Iterable umkehren möchten, können Sie die integrierte Funktion reversed() verwenden.

Die Funktion reversed() verwendet ein Iterable als Argument und gibt einen Iterator zurück, der die Elemente in umgekehrter Reihenfolge liefert:

>>> reversed([0, 1, 2, 3, 4, 5])
<list_reverseiterator object at 0x107062b30>

>>> list(reversed([0, 1, 2, 3, 4, 5]))
[5, 4, 3, 2, 1, 0]

In diesem Beispiel rufen Sie reversed() mit einer Liste von Zahlen auf. Die Funktion gibt einen umgekehrten Iterator zurück. Um seinen Inhalt anzuzeigen, können Sie die Funktion list() verwenden, um eine Liste aus dem Iterator zu erstellen.

Wenn Sie die Werte in einer Iterable sortieren müssen, können Sie ebenfalls die Funktion sorted() verwenden. Diese Funktion hat die folgende Signatur:

sorted(iterable, key=None, reverse=False)

Das erste Argument ist ein iterierbares Objekt, beispielsweise eine Zeichenfolge, eine Liste, ein Tupel oder ein Wörterbuch. Dann haben Sie die Argumente key und reverse, die die folgende Bedeutung haben:

key

Gibt eine Funktion mit einem Argument an, die einen Vergleichsschlüssel aus jedem Element in der Eingabe-Iterable extrahiert

reverse

Ist ein boolescher Wert, der es Ihnen ermöglicht, die Elemente in umgekehrter Reihenfolge zu sortieren, wenn Sie ihn auf True setzen

Es ist wichtig zu beachten, dass das Argument key Funktionsobjekte akzeptiert. Mit anderen Worten: Funktionen ohne die aufrufenden Klammern.

Hier sind einige Beispiele für die Verwendung von sorted() mit verschiedenen integrierten Containern als Argumente:

>>> sorted("bdeac")
['a', 'b', 'c', 'd', 'e']

>>> sorted([4, 2, 7, 5, 1, 6, 3])
[1, 2, 3, 4, 5, 6, 7]

>>> sorted([4, 2, 7, 5, 1, 6, 3], reverse=True)
[7, 6, 5, 4, 3, 2, 1]

Im Gegensatz zu reversed() gibt die Funktion sorted() immer ein Listenobjekt und keinen Iterator zurück. Im ersten Beispiel verwenden Sie eine Zeichenfolge als Argument für sorted() und erhalten eine Liste von Zeichen in alphabetischer Reihenfolge. Unter der Haube verwendet Python den Unicode-Codepunkt des Zeichens, um Zeichenfolgen zu vergleichen.

Im dritten Beispiel setzen Sie das Argument reverse auf True und erhalten die Liste der Zahlen in umgekehrter Reihenfolge sortiert.

Schließlich kann das Argument key in mehreren Situationen nützlich sein. Ein häufiger Anwendungsfall für dieses Argument ist, wenn Sie Elemente sortieren müssen, die auch Container sind. Hier ist ein Beispiel für das Sortieren einer Liste von Tupeln mit zwei Werten:

>>> points = [(1, 2), (3, 1), (4, 0), (2, 1)]

>>> sorted(points, key=lambda point: point[0])
[(1, 2), (2, 1), (3, 1), (4, 0)]

>>> sorted(points, key=lambda point: point[1])
[(4, 0), (3, 1), (2, 1), (1, 2)]

In der ersten hervorgehobenen Zeile verwenden Sie eine lambda-Funktion, die einen Punkt als Argument verwendet und seine erste Koordinate zurückgibt. Dieses Beispiel würde aufgrund der Art und Weise, wie Python Tupel vergleicht, zum gleichen Ergebnis führen, wenn Sie sorted() ohne key aufrufen. In der zweiten hervorgehobenen Zeile gibt die Funktion lambda die zweite Koordinate zurück. Diese Funktionen stellen Vergleichsschlüssel für die Sortiervorgänge bereit.

Im ersten Beispiel sortieren Sie die Punkte also nach ihrer ersten Koordinate, während Sie im zweiten Beispiel die Punkte nach ihrer zweiten Koordinate sortieren.

Bestimmen des Wahrheitswerts von Elementen in Iterables: all() und any()

Manchmal müssen Sie möglicherweise feststellen, ob alle Elemente in einer Iterable wahr sind. Zu diesem Zweck verfügt Python über die integrierte Funktion all(). Zu anderen Zeiten müssen Sie möglicherweise herausfinden, ob mindestens ein Element in einer Iterable wahr ist. Zu diesem Zweck verfügt Python über die integrierte Funktion any().

Die Signatur von all() und any() ist unten dargestellt:

all(iterable)

any(iterable)

Beide Funktionen verwenden eine Iterable von Objekten als Argument. Die Funktion all() gibt True zurück, wenn alle Elemente in der Eingabeiterable wahr sind, und False, wenn mindestens ein Element falsch ist.

Hier sind einige Beispiele für die Funktionsweise von all():

>>> all([1, 2, 3, 4])
True
>>> all([1, 2, 3, 4, 0])
False

>>> all(["Hello", ""])
False
>>> all(["Hello", "World"])
True

In den ersten beiden Beispielen verwenden Sie all() mit einer Liste von Zahlen. Die erste Liste enthält ganzzahlige Werte, die sich von 0 unterscheiden, was Python als wahr ansieht. all() gibt also True zurück. Dann fügen Sie im zweiten Beispiel eine 0 zur Liste hinzu und all() gibt False zurück, da dieser Wert in Python als falsch gilt .

In den letzten beiden Beispielen verwenden Sie eine Liste von Zeichenfolgen. Python betrachtet eine leere Zeichenfolge als falsch, daher gibt all() False zurück. Schließlich übergeben Sie eine Liste mit zwei nicht leeren Zeichenfolgen und all() führt True erneut aus.

Möglicherweise finden Sie im realen Code mehrere Anwendungsfälle für all(). Vielleicht ist die Übergabe eines Generatorausdrucks als Argument an all() eine der leistungsstärksten Möglichkeiten, die Funktion zu verwenden. Angenommen, Sie möchten feststellen, ob alle Zahlen in einer Liste in einem bestimmten Intervall liegen. In dieser Situation können Sie all() wie im folgenden Code verwenden:

>>> numbers = [10, 5, 6, 4, 7, 8, 18]

>>> # Between 0 and 10
>>> all(0 <= x <= 10 for x in numbers)
False

>>> # Between 0 and 20
>>> all(0 <= x <= 20 for x in numbers)
True

In der ersten hervorgehobenen Zeile verwenden Sie einen Generatorausdruck als Argument für all(). Der Generator prüft, ob die Zahlen zwischen 0 und 10 liegen und generiert boolesche Werte entsprechend dem Ergebnis der Bedingung.

Die Funktion all() prüft, ob alle generierten Werte True sind. Wenn das der Fall ist, erhalten Sie True. Wenn andererseits mindestens einer der generierten Werte False ist, erhalten Sie False.

Im Gegensatz zu all() gibt die Funktion any() True zurück, wenn mindestens ein Element wahr ist, und False wenn alle Elemente falsch sind. Sie können also any() verwenden, wenn Sie feststellen müssen, ob mindestens ein Element in einem Iterable wahr ist.

Hier sind ein paar Beispiele für die Verwendung von any() in Python:

>>> any([0, 0.0, False, "", []])
False

>>> any([0, 0.0, False, "", [], 42])
True

Im ersten Beispiel sind alle Objekte in der Eingabeliste gemäß Pythons internen Regeln zur Bestimmung des Wahrheitswerts eines Objekts falsch. Da alle Objekte falsch sind, gibt any() False zurück. Im zweiten Beispiel fügen Sie die Zahl 42 am Ende der Eingabeliste hinzu. Da 42 wahr ist, gibt any() True zurück.

Auch hier kann die Funktion any(), genau wie all(), glänzen, wenn Sie sie mit einem Generatorausdruck verwenden, der nach einer Bedingung prüft. Angenommen, Sie möchten wissen, ob mindestens ein Buchstabe in einem bestimmten Text in Großbuchstaben geschrieben ist. In dieser Situation können Sie etwa Folgendes tun:

>>> any(letter.isupper() for letter in  "hello, world!")
False

>>> any(letter.isupper() for letter in  "Hello, World!")
True

In diesen Beispielen verwenden Sie die Methode str.isupper(), um zu bestimmen, ob ein Buchstabe in Großbuchstaben geschrieben ist. Diese Methode gibt True oder False zurück, sodass Sie eine Iterable boolescher Werte erhalten. Die Aufgabe von any() besteht darin, festzustellen, ob einer dieser Werte wahr ist.

Im ersten Beispiel haben Sie keine Großbuchstaben, daher gibt any() False zurück. Im zweiten Beispiel haben Sie ein großes H, sodass any() True zurückgibt.

Bereiche ganzzahliger Werte erstellen: range()

Manchmal müssen Sie numerische Bereiche erstellen, um eine Reihe ganzzahliger Werte in einem bestimmten Intervall darzustellen. Normalerweise müssen die Zahlen fortlaufend sein, Sie möchten aber möglicherweise auch, dass sie nicht fortlaufend sind.

Sie können beispielsweise mithilfe einer Python-Liste einen Wertebereich erstellen, der alle Ziffern enthält:

[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]

Dieser Ansatz funktioniert, wenn Ihr Bereich relativ klein ist, wie in diesem Beispiel. Was aber, wenn Ihr Bereich eine Million Werte haben muss? Der Aufbau eines solchen Bereichs mit einer Liste wäre eine schwierige Aufgabe. Es gibt einen besseren Weg.

Python verfügt über die integrierte Funktion range(), um die Erstellung numerischer Bereiche zu erleichtern:

>>> range(10)
range(0, 10)

>>> list(range(10))
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]

>>> range(1_000_000)
range(0, 1000000)

>>> list(range(1_000_000))
[1, 2, 3,
 ...,
 999998, 999999]

Die Funktion range() gibt ein range-Objekt statt einer Liste zurück. Wenn Sie die Werte in einem konkreten Bereich überprüfen möchten, können Sie ihn wie im zweiten Beispiel in einen Aufruf von list() einbinden. Jetzt haben Sie eine Liste mit Ziffern.

Im dritten Beispiel erstellen Sie einen Bereich mit einer Million Ganzzahlen von 0 bis 999999. Wenn Sie es in Aktion sehen möchten, übergeben Sie es an list(). Sie erhalten ein Terminalfenster voller Zahlen!

Die integrierte Funktion range() hat die folgenden Signaturen:

range(stop)
range(start, stop, step=1)

Sie haben eine Ein-Argument- und eine Drei-Argument-Variante der Funktion. Hier ist, was jedes Argument bedeutet:

start

Es enthält den Anfangswert im Bereich. Der Standardwert ist 0 und ist im Bereich enthalten.

stop

Es enthält den Wert, bei dem der Bereich endet. Es ist ein erforderliches Argument und sein Wert ist nicht im Bereich enthalten.

step

Es hält den Schritt durch aufeinanderfolgende Werte. Es handelt sich um ein optionales Argument, dessen Standardwert 1 ist.

Bisher haben Sie die Ein-Argument-Variante verwendet, die den Bereich bei 0 beginnt und einen Bereich aufeinanderfolgender Ganzzahlen aufbaut. Hier sind einige Beispiele, die die Variante mit drei Argumenten zeigen:

>>> list(range(1, 11))
[1, 2, 3, 4, 5, 6, 7, 8, 9, 10]

>>> list(range(10, 101, 10))
[10, 20, 30, 40, 50, 60, 70, 80, 90, 100]

Beachten Sie, dass in der Variante mit drei Argumenten das dritte Argument optional ist. Das bedeutet, dass Sie die Funktion mit zwei Argumenten aufrufen und sich auf den Standardwert von step verlassen können, der 1 ist. Das machen Sie im ersten Beispiel, das einen Bereich aufeinanderfolgender Ganzzahlen von 1 bis 11 erstellt. Auch hier ist 11 nicht im endgültigen Bereich enthalten, da es sich um den Wert handelt, bei dem range() keine Werte mehr ausgibt.

Im zweiten Beispiel erstellen Sie einen Bereich, der bei 10 beginnt und mit einer Schrittweite von 10101 reicht >.

Sie können auch negative Werte für die Argumente von range() verwenden. Ein häufiger Anwendungsfall hierfür ist, wenn Sie Bereiche negativer Zahlen und Bereiche erstellen müssen, die rückwärts zählen:

>>> list(range(-10, 0))
[-10, -9, -8, -7, -6, -5, -4, -3, -2, -1]

>>> list(range(100, 0, -10))
[100, 90, 80, 70, 60, 50, 40, 30, 20, 10]

In diesem Beispiel enthält der erste Bereich aufeinanderfolgende negative Zahlen von -10 bis 0. Der zweite Bereich zählt rückwärts von 100 bis 0 mit einer Schrittweite von -10.

Bereiche können in verschiedenen Situationen nützlich sein. Ein guter Anwendungsfall für einen Bereich ist, wenn Sie eine Operation eine bestimmte Anzahl von Malen ausführen müssen:

>>> for _ in range(3):
...     print("Beep")
...
Beep
Beep
Beep

Diese Schleife wird dreimal ausgeführt und gibt eine Meldung auf dem Bildschirm aus. Allerdings muss die Schleife die Schleifenvariable nicht in ihrem Rumpf verwenden. Sie verwenden also einen Unterstrich, um anzuzeigen, dass es sich um eine Wegwerfvariable handelt.

Ein häufiger Missbrauch von range-Objekten in Python besteht darin, sie als Möglichkeit zu verwenden, eine Schleife über ein vorhandenes Iterable durchzuführen:

>>> letters = ["a", "b", "c", "d"]

>>> for index in range(len(letters)):
...     print(index, letters[index])
...
0 a
1 b
2 c
3 d

Diese Art von for-Schleife ist nicht das beste Beispiel für ein Python-Konstrukt. Es verwendet range(), um die Buchstaben mit numerischen Indizes zu durchlaufen. Im folgenden Abschnitt erfahren Sie mehr über die Pythonic-Methode zum Schreiben dieser Art von Schleife.

Aufzählen von Elementen in Schleifen: enumerate()

Eine pythonische for-Schleife durchläuft die Elemente in einer Iterable, ohne den Index zu berücksichtigen, an dem sich ein bestimmtes Element befindet, oder die Reihenfolge, in der die Elemente verarbeitet wurden. Sie werden feststellen, dass die meisten Python-for-Schleifen etwa wie folgt aussehen:

>>> colors = ["red", "orange", "yellow", "green"]

>>> for color in colors:
...     print(color)
...
red
orange
yellow
green

Diese Art, Schleifen in Python zu schreiben, ist explizit und intuitiv, was sich stark auf die Lesbarkeit der Schleife auswirkt. Manchmal benötigen Sie jedoch eine Möglichkeit, auf den Index zuzugreifen, in dem sich ein bestimmtes Element im Eingabeiterable befindet.

Wenn Sie mit Python beginnen und in einer Schleife auf Indizes zugreifen müssen, kann es oft vorkommen, dass Sie eine Schleife wie die folgende schreiben:

>>> for index in range(len(colors)):
...     print(index, colors[index])
...
...
0 red
1 orange
2 yellow
3 green
4 blue
5 indigo
6 violet

Diese Art von Schleife funktioniert. Es handelt sich jedoch nicht um das, was man als Pythonic-Schleife bezeichnen kann. Es verwendet ein paar Tricks, um die Iteration über Indizes irgendwie nachzuahmen. Python bietet dafür ein besseres Tool, und dieses Tool ist die integrierte Funktion enumerate().

So schreiben Sie die obige Schleife mit der Funktion enumerate():

>>> for index, color in enumerate(colors):
...     print(index, color)
...
0 red
1 orange
2 yellow
3 green
4 blue
5 indigo
6 violet

Diese Schleife ist lesbar und explizit. Die Funktion enumerate() verwendet ein Iterable als Argument und generiert Tupel mit zwei Elementen, die einen ganzzahligen Index und das zugehörige Element enthalten.

Hier ist die Signatur der Funktion:

enumerate(iterable, start=0)

Das erste Argument ist ein iterierbares Objekt. Das zweite Argument, start, gibt Ihnen die Möglichkeit, einen Startwert für die Aufzählung zu definieren. Der Standardwert ist 0, da dies der übliche Startwert von Indizes in der Programmierung ist. In manchen Situationen kann es jedoch praktisch sein, einen anderen Ausgangspunkt zu verwenden, z. B. 1.

Um zu veranschaulichen, wie das Argument start verwendet wird, nehmen wir an, dass Sie eine textbasierte Benutzeroberflächenanwendung (TUI) erstellen und ein Menü mit einigen Optionen anzeigen möchten. Den Optionen sollte eine Nummer zugeordnet sein, damit der Benutzer die gewünschte Aktion auswählen kann. In dieser Situation können Sie enumerate() wie im folgenden Code verwenden:

>>> def list_menu(options):
...     print("Main Menu:")
...     for index, option in enumerate(options, start=1):
...         print(f"{index}. {option}")
...

>>> list_menu(["Open", "Save", "Settings", "Quit"])
Main Menu:
1. Open
2. Save
3. Settings
4. Quit

Aus der Sicht des Endbenutzers ist es der natürliche Weg, die Menüliste bei 1 zu beginnen. Sie können diesen Effekt erzielen, indem Sie im Aufruf von enumerate() start auf 1 setzen. Jetzt beginnt das Menü bei 1 statt bei 0.

Extrahieren von Slices oder Teilen von Sequenzen: slice()

Wenn Sie mit Python arbeiten, müssen Sie möglicherweise einen Teil oder ein Segment einer vorhandenen Sequenz extrahieren, beispielsweise einen String, eine Liste oder ein Tupel. Dazu verwenden Sie normalerweise den Slicing-Operator ([]). Sie können jedoch auch die integrierte Funktion slice() verwenden. Die Funktion slice() hat die folgenden Signaturen:

slice(stop)
slice(start, stop, step=None)

Die Funktion slice() gibt ein slice-Objekt zurück, das den durch range(start, stop, step) angegebenen Satz von Indizes darstellt. Die Argumente haben hier eine ähnliche Bedeutung wie in der Funktion range():

start

Es enthält den Anfangswert im Slice. Der Standardwert ist None, was den Beginn der Sequenz angibt.

stop

Es enthält den Wert, bei dem das Slice stoppt. Es ist ein erforderliches Argument und sein Wert ist nicht im Slice enthalten. Wenn es auf None gesetzt ist, bedeutet es das Ende der Sequenz (len(sequence)).

step

Es hält den Schritt durch aufeinanderfolgende Werte. Es handelt sich um ein optionales Argument, das standardmäßig None ist, was einen Schritt von 1 bedeutet.

Slices stellen keine numerischen Bereiche dar, sondern Sätze von Indizes. Mit diesen Indizes können Sie einen Teil einer Liste extrahieren. Hier ein paar Beispiele:

>>> numbers = [1, 2, 3, 4, 5, 6, 7, 8, 9]

>>> even = numbers[slice(1, None, 2)]
>>> even
[2, 4, 6, 8]

>>> odd = numbers[slice(None, None, 2)]
>>> odd
[1, 3, 5, 7, 9]

Im ersten Abschnitt beginnen Sie bei 1 und gehen mit einem Schritt von 2 bis zum Ende der Liste. Dieses Segment gibt Ihnen eine Liste gerader Zahlen. Im zweiten Beispiel beginnen Sie am Anfang der Liste und gehen mit einem Schritt von 2 bis zum Ende der Liste. Mit diesem Slice erhalten Sie eine Liste ungerader Zahlen.

Beachten Sie, dass Sie in den meisten Python-Codes slice() nicht wie im obigen Beispiel sehen oder verwenden. In den meisten Fällen verwenden Sie den Slicing-Operator [start:stop:step]. So sieht das mit diesem Operator aus:

>>> even = numbers[1::2]
>>> even
[2, 4, 6, 8]

>>> odd = numbers[::2]
>>> odd
[1, 3, 5, 7, 9]

In diesen Beispielen verwenden Sie den Slicing-Operator, um die geraden und ungeraden Zahlen aus Ihrer ursprünglichen Liste abzurufen. Beachten Sie, dass das Überspringen eines bestimmten Index dazu führt, dass dieser Index auf seinem Standardwert basiert. Wenn Sie beispielsweise keinen start-Index angeben, wird standardmäßig der Anfang der Liste verwendet.

Iterables für parallele Iteration komprimieren: zip()

Mit der in Python integrierten Funktion zip() können Sie mehrere Iterables parallel durchlaufen. Diese Funktion erstellt einen Iterator, der Elemente aus zwei oder mehr Iterables aggregiert und so Tupel mit Werten ergibt.

Hier ist die Signatur der integrierten Funktion zip():

zip(*iterables, strict=False)

Diese Funktion verwendet eine undefinierte Anzahl von Iterables als Argumente und liefert bei Bedarf Tupel von Elementen. Die Tupel enthalten ein Element aus jeder iterierbaren Eingabe, was sie ideal für die parallele Iteration macht.

Hier einige kurze Beispiele:

>>> letters = ["a", "b", "c"]
>>> numbers = [1, 2, 3]
>>> operators = ["*", "/", "+"]

>>> for characters in zip(letters, numbers, operators):
...     print(characters)
...
('a', 1, '*')
('b', 2, '/')
('c', 3, '+')

>>> for l, n, o in zip(letters, numbers, operators):
...     print(f"{l} {n} {o}")
...
a 1 *
b 2 /
c 3 +

In der ersten Schleife verwenden Sie eine einzelne Schleifenvariable, um jedes Tupel zu speichern, das Sie von zip() erhalten. Das erste Tupel enthält die ersten Elemente jedes Eingabeiterables. Das zweite Tupel enthält die zweiten Elemente und so weiter. In der zweiten Schleife verwenden Sie drei Schleifenvariablen, um die Elemente jedes generierten Tupels zu entpacken.

Ein schöner Anwendungsfall von zip() ist, wenn Sie zwei Listen haben und daraus ein Wörterbuch erstellen möchten. Betrachten Sie das folgende Beispiel:

>>> keys = ["name", "age", "country"]
>>> values = ["Jane", "30", "Canada"]

>>> dict(zip(keys, values))
{'name': 'Jane', 'age': '30', 'country': 'Canada'}

In diesem Beispiel kombinieren Sie zwei vorhandene Listen mit zip() und übergeben die resultierenden Tupel an die Funktion dict(), um ein Wörterbuch zu erstellen.

Das strict-Argument für zip() wurde in Python 3.10 hinzugefügt und ist ein Nur-Schlüsselwort-Argument, das eine sichere Möglichkeit bietet, Iterables ungleicher Länge zu verarbeiten. Der Standardwert des Arguments ist False, was bedeutet, dass zip() nur so viele Tupel generiert wie Elemente im kürzesten Iterable.

Wenn Sie strict auf True setzen, erhalten Sie eine ValueError-Ausnahme, wenn die Eingabe-Iterables nicht die gleiche Länge haben:

>>> list(zip(range(5), range(100)))
[(0, 0), (1, 1), (2, 2), (3, 3), (4, 4)]

>>> list(zip(range(5), range(100), strict=True))
Traceback (most recent call last):
    ...
ValueError: zip() argument 2 is longer than argument 1

Im ersten Argument verlassen Sie sich auf den Standardwert von strict und erhalten fünf Tupel, da der kürzeste Bereich nur fünf Werte hat. Im zweiten Beispiel setzen Sie strict auf True. Diesmal erhalten Sie eine Fehlermeldung, da die Eingabebereiche nicht die gleiche Anzahl an Werten aufweisen.

Erstellen und Konsumieren von Iteratoren: iter() und next()

In Python implementieren Iteratoren das Iterator-Entwurfsmuster, das es Ihnen ermöglicht, einen Container zu durchlaufen und auf seine Elemente zuzugreifen. Das Iteratormuster entkoppelt die Iterationsalgorithmen von Containern wie Listen, Tupeln, Wörterbüchern und Mengen.

Python verfügt über zwei integrierte Funktionen, die Ihnen bei der Arbeit mit Iteratoren helfen können. Mit der Funktion iter() können Sie einen Iterator aus einem Iterable erstellen, und mit der Funktion next() können Sie einen Iterator elementweise konsumieren.

Betrachten Sie das folgende Spielzeugbeispiel:

>>> colors = ["red", "orange", "yellow", "green"]

>>> colors_it = iter(colors)
>>> colors_it
<list_iterator object at 0x10566a170>

>>> next(colors_it)
'red'
>>> next(colors_it)
'orange'
>>> next(colors_it)
'yellow'
>>> next(colors_it)
'green'
>>> next(colors_it)
Traceback (most recent call last):
    ...
StopIteration

In diesem Beispiel verwenden Sie die Funktion iter(), um ein Iteratorobjekt aus einer vorhandenen Farbliste zu erstellen. Im Gegensatz zu Iterables unterstützen Iteratoren die Funktion next(). Wenn Sie diese Funktion mit einem Iterator als Argument aufrufen, erhalten Sie beim ersten Aufruf das erste Element. Wenn Sie die Funktion erneut aufrufen, erhalten Sie das zweite Element und so weiter.

Wenn Sie alle Elemente im Iterator durchlaufen, löst next() eine StopIteration-Ausnahme aus. Python verwendet diese Ausnahme intern, um den Iterationsprozess in einer for-Schleife oder einem Verständnis zu stoppen. Beachten Sie, dass Sie einen Iterator nur einmal durchlaufen können. Danach ist der Iterator erschöpft oder verbraucht.

Hier sind die Signaturen von iter() :

iter(iterable)
iter(object, sentinel)

In der ersten Signatur repräsentiert iterable jeden iterierbaren Typ. In der zweiten Signatur muss das Argument object ein aufrufbares Argument sein. Sie haben die erste Signatur bereits in Aktion gesehen. Jetzt ist es an der Zeit, einen kurzen Blick auf die zweite Signatur zu werfen.

Um dies anhand eines Beispiels zu veranschaulichen, nehmen wir an, dass Sie an einer Befehlszeilenschnittstellen-App (CLI) arbeiten und die Eingaben des Benutzers so lange berücksichtigen möchten, bis er das Wort "done" eingibt. So können Sie dies mit der Funktion iter() tun:

>>> def read_user_input():
...     print("Enter word (type 'done' to finish):")
...     for word in iter(input, "done"):
...         print(f"Processing word: '{word}'")
...

>>> read_user_input()
Enter word (type 'done' to finish):
Python
Processing word: 'Python'
Programming
Processing word: 'Programming'
Iterators
Processing word: 'Iterators'
done

In der hervorgehobenen Zeile verwenden Sie iter() mit zwei Argumenten. Für das erste Argument verwenden Sie die integrierte Funktion input(), mit der Sie Eingaben vom Benutzer entgegennehmen können. Beachten Sie, dass Sie die Funktion nicht aufrufen, sondern als Funktionsobjekt übergeben.

Dann haben Sie das Wort "done", das als Wächter fungiert. Mit anderen Worten: iter() ruft input() für Sie auf und löst eine StopIteration-Ausnahme aus, wenn der Rückgabewert mit dem Sentinel-Wort übereinstimmt.

Wenn Sie die Funktion aufrufen, werden Sie aufgefordert, ein Wort einzugeben. Anschließend verarbeitet der Code das Wort und ermöglicht Ihnen die Eingabe eines weiteren Worts. Diese Aktionen wiederholen sich, bis Sie Ihren Sentinel eingeben, das Wort "erledigt".

Wenn es um die Funktion next() geht, haben Sie auch zwei verschiedene Signaturen, die etwa so aussehen:

next(iterator)
next(iterator, default)

Sie haben erneut gesehen, wie Sie next() mit einem Iterable als eindeutigem Argument verwenden. Jetzt können Sie sich auf die Verwendung der zweiten Signatur konzentrieren. In diesem Fall haben Sie ein zweites Argument namens default. Mit diesem Argument können Sie den Wert angeben, den Sie zurückgeben möchten, wenn die Eingabe-Iterable erschöpft ist oder ihre Daten überschritten sind:

>>> count_down = iter([3, 2, 1])

>>> next(count_down, 0)
3
>>> next(count_down, 0)
2
>>> next(count_down, 0)
1
>>> next(count_down, 0)
0
>>> next(count_down, 0)
0

In diesem Beispiel erstellen Sie einen Iterator aus einer Liste von Zahlen. Anschließend verwenden Sie next(), um den Iterator jeweils eine Zahl nach der anderen zu verbrauchen. Nachdem next() den gesamten Iterator verbraucht hat, erhalten Sie als Ergebnis 0, da dies der Wert ist, den Sie an default, das zweite Positionsargument, übergeben haben . Aufeinanderfolgende Aufrufe der Funktion geben ebenfalls 0 zurück.

Iterables filtern und zuordnen: filter() und map()

Haben Sie schon einmal von funktionaler Programmierung gehört? Es handelt sich um ein Programmierparadigma, bei dem ein Programm von Aufrufen reiner Funktionen dominiert wird, also Funktionen, deren Ausgabewerte ausschließlich von ihren Eingabewerten abhängen, ohne dass es zu beobachtbaren Nebenwirkungen kommt.

Python ist nicht das, was man eine funktionale Programmiersprache nennen könnte. Es verfügt jedoch über einige integrierte Funktionen, die klassische Funktionswerkzeuge sind. Bei diesen Tools handelt es sich um die integrierten Funktionen filter() und map().

Sie können die Funktion filter() verwenden, um Werte aus Iterables zu extrahieren, was als Filtervorgang bezeichnet wird.

Die Signatur von filter() sieht etwa so aus:

filter(function, iterable)

Das erste Argument, function, muss eine Funktion mit einem Argument sein, während das zweite Argument eine beliebige iterierbare Python-Funktion sein kann. Hier ist eine kurze Beschreibung dieser Argumente:

function

Ein Prädikat oder eine boolesche Funktion, die ein einzelnes Argument akzeptiert

iterable

Ein iterierbares Python

Das Argument function ist eine Entscheidungsfunktion, auch bekannt als Filterfunktion. Es liefert die Kriterien für die Entscheidung, ob ein bestimmter Wert beibehalten werden soll.

In der Praxis wendet filter() die Funktion auf alle Elemente in iterable an. Anschließend wird ein Iterator erstellt, der nur die Elemente liefert, die die von der Funktion überprüften Kriterien erfüllen. Mit anderen Worten: Es werden die Elemente zurückgegeben, die dafür sorgen, dass function True zurückgibt.

Mit der Funktion filter() können Sie Iterables ohne formale Schleife verarbeiten. Hier ist ein Beispiel für die Verwendung von filter() zum Extrahieren gerader Zahlen aus einer Werteliste:

>>> numbers = [1, 3, 10, 45, 6, 50]

>>> list(filter(lambda n: n % 2 == 0, numbers))
[10, 6, 50]

In diesem Beispiel nimmt die Funktion lambda eine ganze Zahl an und gibt True zurück, wenn der Eingabewert eine gerade Zahl ist, andernfalls False. Der Aufruf von filter() wendet diese lambda-Funktion auf die Werte in numbers an, filtert die ungeraden Zahlen heraus und gibt die geraden Zahlen zurück. Beachten Sie, dass Sie die Funktion list() verwenden, um eine Liste aus dem Iterator zu erstellen, den filter() zurückgibt.

Die Funktion map() ist ein weiteres gängiges Werkzeug in der funktionalen Programmierung. Mit dieser Funktion können Sie eine Transformationsfunktion auf alle Werte in einem Iterable anwenden.

Pythons map() hat die folgende Signatur:

map(function, iterable, *iterables)

Die Funktion map() wendet function auf jedes Element in iterable in einer Schleife an und gibt einen neuen Iterator zurück, der bei Bedarf transformierte Elemente liefert.

Hier ist eine Zusammenfassung der Argumente und ihrer Bedeutung:

function

Eine Python-Funktion, die eine Anzahl von Argumenten entgegennimmt, die der Anzahl der Eingaben entspricht. iterierbare Elemente

iterable

Ein erforderliches Argument, das jedes Python-Iterable enthalten kann.

*iterables

Eine variable Anzahl von Python-Iterables.

Das Argument function ist eine sogenannte Transformationsfunktion. Es wendet eine bestimmte Transformation auf seine Argumente an und gibt einen transformierten Wert zurück.

Um zu veranschaulichen, wie map() funktioniert, nehmen wir an, dass Sie zwei Listen haben. Die erste Liste enthält eine Reihe von Werten, die Sie als Grundlage für Leistungsberechnungen verwenden möchten. Die zweite Liste enthält die Exponenten, die Sie auf jede Basis anwenden möchten. Sie können die Funktion map() verwenden, um diese Listen zu verarbeiten und einen Iterator von Potenzen zu erhalten:

>>> bases = [8, 5, 2]
>>> exponents = [2, 3, 4]

>>> list(map(pow, bases, exponents))
[64, 125, 16]

In diesem Beispiel verwenden Sie die integrierte Funktion pow() als erstes Argument für map(). Wie Sie bereits erfahren haben, nimmt pow() eine Basis und einen Exponenten als Argumente und gibt die Potenz zurück. Anschließend übergeben Sie die Basen und Exponenten an map(), damit die gewünschten Potenzen berechnet werden.

Eingabe und Ausgabe verarbeiten

Wenn Sie Eingaben vom Benutzer oder von Dateien entgegennehmen und die Ausgabe dem Benutzer präsentieren müssen, sollten Sie wissen, dass die Sprache über einige integrierte Funktionen verfügt, die Ihnen bei diesen Aufgaben helfen können:

input()

Liest Eingaben von der Konsole

open()

Öffnet eine Datei und bietet Zugriff auf ein Dateiobjekt

print()

Druckt in einen Textstream oder die Konsole

format()

Konvertiert einen Wert in eine formatierte Darstellung

In den folgenden Abschnitten erfahren Sie, wie Sie diese Funktionen zum Verarbeiten von Eingabe- und Ausgabevorgängen in Ihrem Python-Code verwenden.

Eingaben vom Benutzer akzeptieren: input()

Das Einholen von Eingaben Ihrer Benutzer ist ein häufiger Vorgang in CLI- und textbasierten Schnittstellenanwendungen (TUI). Python verfügt über eine integrierte Funktion, die speziell auf diese Art von Operation ausgerichtet ist. Die Funktion heißt praktischerweise input().

Die integrierte Funktion input() liest die Eingaben des Benutzers und erfasst sie als Zeichenfolge. Hier ist die Signatur der Funktion:

input([prompt])

Die eckigen Klammern um prompt weisen darauf hin, dass dieses Argument optional ist. Mit diesem Argument können Sie eine Eingabeaufforderung bereitstellen, um den Benutzer nach der erforderlichen oder gewünschten Eingabe zu fragen.

Nehmen wir als Beispiel für die Verwendung von input() an, dass Sie ein Zahlen-Ratespiel erstellen möchten. Das Spiel fordert den Benutzer auf, eine Zahl von 1 bis 10 einzugeben und zu prüfen, ob der Eingabewert mit einer Geheimzahl übereinstimmt.

Hier ist der Code für das Spiel:

from random import randint

LOW, HIGH = 1, 10

secret_number = randint(LOW, HIGH)
clue = ""

while True:
    guess = input(f"Guess a number between {LOW} and {HIGH} {clue} ")
    number = int(guess)
    if number > secret_number:
        clue = f"(less than {number})"
    elif number < secret_number:
        clue = f"(greater than {number})"
    else:
        break

print(f"You guessed it! The secret number is {number}")

In diesem Code definieren Sie eine Endlosschleife, in der Sie den Benutzer auffordern, seine Schätzung abzugeben, indem er eine Zahl zwischen 1 und 10 eingibt. Die erste Zeile in der Schleife ist ein Aufruf des integrierten input() Funktion. Sie haben eine beschreibende Eingabeaufforderung verwendet, um die Benutzer darüber zu informieren, was zu tun ist.

Fahren Sie fort und führen Sie das Skript über Ihre Befehlszeile aus, um es auszuprobieren:

$ python guess.py
Guess a number between 1 and 10  2
Guess a number between 1 and 10 (greater than 2) 3
Guess a number between 1 and 10 (greater than 3) 8
Guess a number between 1 and 10 (less than 8) 6
You guessed it! The secret number is 6

Cool! Ihr Spiel fordert den Benutzer auf, eine Zahl einzugeben, vergleicht diese mit der Geheimzahl und teilt dem Benutzer mit, wenn er richtig geraten hat. Die Funktion input() spielt eine zentrale Rolle im Spielablauf und ermöglicht es Ihnen, die Eingaben des Benutzers abzurufen und zu verarbeiten.

Dateien öffnen: open()

Das Lesen und Schreiben von Dateien sind häufige Programmieraufgaben. In Python können Sie für diese Zwecke die integrierte Funktion open() verwenden. Normalerweise verwenden Sie die Funktion open() in einer with-Anweisung.

Nehmen wir als kurzes Beispiel an, dass Sie eine Textdatei mit folgendem Inhalt haben:

apple
banana
cherry
orange
mango

Sie möchten die Datei öffnen und ihren Inhalt lesen, während Sie sie auf dem Bildschirm ausdrucken. Dazu können Sie den folgenden Code verwenden:

>>> with open("fruits.txt") as file:
...     print(file.read())
...
apple
banana
cherry
orange
mango

In dieser with-Anweisung rufen Sie open() mit dem Dateinamen als Argument auf. Dieser Aufruf öffnet die Datei zum Lesen. Die open()-Funktion gibt ein Dateiobjekt zurück, das die with-Anweisung den file-Variablen mit dem as zuweist Spezifizierer.

Die Funktion open() hat die folgende Signatur:

open(
    file,
    mode="r",
    buffering=-1,
    encoding=None,
    errors=None,
    newline=None,
    closefd=True,
    opener=None,
)

Die Funktion kann bis zu acht Argumente annehmen. Das erste Argument, file, ist das einzige erforderliche Argument. Die restlichen Argumente sind optional. Hier ist eine Zusammenfassung der Bedeutung der Argumente:

Argument Description Comment
file A path-like object holding the path to the target file It’s a required argument.
mode A string that specifies the mode in which you want to open the file It defaults to "r", which is the reading mode. You’ll learn about the available modes in a moment.
buffering An integer that sets the buffering policy You can pass 0 to switch buffering off, which is only possible in binary mode. You can use 1 to select line buffering, which is only usable in text mode. Finally, you can use an integer greater than 1 to indicate the size in bytes of a fixed-size chunk buffer.
encoding The name of the encoding used to decode or encode the file You can only use this argument in text mode.
errors A string that specifies how encoding and decoding errors are to be handled You can only use this argument in text mode. It can take one of the following values: "strict", "ignore", "replace", "surrogateescape", "xmlcharrefreplace", "backslashreplace", or "namereplace". These values have similar meanings to those you learned in the section about the ord() and chr() functions.
newline A string that determines how to parse newline characters from the stream It can be None, "", "\n", "\r", or "\r\n".
closefd A Boolean value that defines whether you want to close a file descriptor It can be False when you provide a file descriptor instead of a filename and want the descriptor to remain open when the file is closed. Otherwise, it must be True.
opener A callable that you use as a custom opener for the target file The opener must return an open file descriptor.

In diesem Tutorial werden Sie nicht alle diese Argumente behandeln. Stattdessen lernen Sie zwei der am häufigsten verwendeten Argumente kennen, nämlich mode und encoding.

Hier ist eine Liste der zulässigen mode-Werte:

"r"

Öffnet die Datei zum Lesen und ist der Standardwert

"w"

Öffnet die Datei zum Schreiben, wobei die Datei zunächst abgeschnitten wird

"x"

Öffnet die Datei zur exklusiven Erstellung. Dies schlägt fehl, wenn die Datei bereits vorhanden ist

"a"

Öffnet die Datei zum Schreiben und hängt die neuen Daten an das Ende der Datei an, sofern diese bereits vorhanden ist

"b"

Öffnet die Datei im Binärmodus

"t"

Öffnet die Datei im Textmodus, dem Standardmodus

"+"

Öffnet die Datei zur Aktualisierung, wodurch Lese- und Schreibvorgänge möglich sind

In dieser Tabelle definieren die Werte "b" und "t" zwei generische Modi für Binär- bzw. Textdateien. Sie können diese beiden Modi mit anderen Modi kombinieren. Mit dem "wb"-Modus können Sie beispielsweise Binärdaten in eine Datei schreiben, mit dem "rt"-Modus können Sie textbasierte Daten aus einer Datei lesen und bald.

Beachten Sie, dass "t" der Standardmodus ist. Wenn Sie also den Modus auf "w" setzen, geht Python davon aus, dass Sie Text in die Zieldatei schreiben möchten.

Hier ist ein Codeausschnitt, der Text in eine Datei in Ihrem Arbeitsverzeichnis schreibt:

>>> with open("hello.txt", "w") as file:
...     file.write("Hello, World!")
...
13

In diesem Beispiel öffnen Sie eine Datei namens hello.txt, damit Sie Text hineinschreiben können. Im Codeblock der with-Anweisung rufen Sie die Methode .write() für das Dateiobjekt auf, um Text zu schreiben. Beachten Sie, dass die Methode die Anzahl der geschriebenen Bytes zurückgibt. Deshalb wird auf dem Bildschirm 13 angezeigt.

Nachdem Sie den Code ausgeführt haben, befindet sich die Datei hello.txt in Ihrem Arbeitsverzeichnis. Fahren Sie fort und öffnen Sie es, um den Inhalt zu überprüfen.

Sie können mit anderen Modi experimentieren und sich ein Bild davon machen, wie sie funktionieren, damit Sie sie sicher in Ihrem Code verwenden können. Betrachten Sie dies als praktische Übung!

Die Verwendung des Arguments encoding ist eine weitere typische Anforderung, wenn Sie mit Textdateien arbeiten. In dieser Situation empfiehlt es sich, die Textkodierung, die Sie in Ihrem Code verwenden, explizit anzugeben. Die UTF-8-Kodierung ist ein häufiges Beispiel für einen Wert, den Sie an encoding übergeben würden:

>>> with open("hello.txt", "w", encoding="utf-8") as file:
...     file.write("Hello, Pythonista!")
...
13

>>> with open("hello.txt", "r", encoding="utf-8") as file:
...     print(file.read())
...
Hello, Pythonista!

In diesem Beispiel verwenden Sie die UTF-8-Kodierung zum Schreiben und Lesen aus einer Textdatei. Beachten Sie, dass Sie den Namen des Arguments explizit verwenden müssen, um den Codierungswert bereitzustellen. Dies liegt daran, dass das folgende Argument in der Liste puffernd und nicht kodierend ist. Wenn Sie den expliziten Namen nicht verwenden, erhalten Sie einen TypeError Ausnahme.

Drucken von Text auf dem Bildschirm oder einer anderen Ausgabe: print()

Eine weitere häufige Anforderung, die beim Erstellen von CLI- oder TUI-Anwendungen auftritt, besteht darin, Informationen auf dem Bildschirm anzuzeigen, um den Benutzer über den Status der App zu informieren. In diesem Fall können Sie die integrierte Funktion print() verwenden, die ein grundlegendes Werkzeug in der Python-Programmierung ist.

Die Funktion print() hat die folgende Signatur:

print(*objects, sep=" ", end="\n", file=None, flush=False)

Durch den Aufruf von print() werden die Eingabeobjekte standardmäßig auf dem Bildschirm gedruckt. Sie können die restlichen Argumente verwenden, um die Funktionsweise der Funktion zu optimieren. Hier ist eine Zusammenfassung der Argumente und ihrer Bedeutung:

*objects

Eine beliebige Anzahl von Python-Objekten

sep

Die Zeichenfolge, die Sie verwenden möchten, um Eingabeobjekte voneinander zu trennen

end

Die Zeichenfolge, die nach dem letzten Eingabeobjekt verwendet werden soll

file

Das geöffnete Dateiobjekt, in das Sie die Eingabeobjekte schreiben möchten

flush

Ein boolescher Wert, der definiert, ob Sie den Ausgabepuffer leeren möchten

Wenn Sie print() aufrufen, nimmt es die eingegebenen Objekte, wandelt sie in Zeichenfolgen um, verbindet sie mit sep und hängt end an . Wenn Sie print() ohne Argument aufrufen, wird end ausgegeben. Beachten Sie, dass die Argumente sep, end, file und flush Schlüsselwortargumente sind.

Hier sind einige Beispiele für die Verwendung der Funktion print():

>>> print()

>>> print("Hello")
Hello
>>> print("Hello", "Pythonista!")
Hello Pythonista!
>>> print("Hello", "Pythonista!", sep="\t")
Hello    Pythonista!
>>> print("Hello", "Pythonista!", sep="\t", end=" 👋\n")
Hello    Pythonista! 👋

Wenn Sie print() ohne Argumente aufrufen, wird end auf dem Bildschirm gedruckt. Dieses Argument ist standardmäßig ein Zeilenumbruchzeichen, das erhalten Sie also. Mit einem Objekt als Argument wird das Objekt gedruckt, gefolgt von einem Zeilenumbruchzeichen. Bei mehreren Objekten als Argumenten werden die Argumente durch sep verbunden und am Ende eine neue Zeile hinzugefügt.

Sie können auch den Wert von end anpassen und Python veranlassen, am Ende Ihrer Ausgabe etwas anderes auszugeben.

Das Argument file verwendet standardmäßig die Standardausgabe, also Ihren Bildschirm. Der Stream sys.stdout stellt diesen Standardwert bereit. Sie können die Ausgabe jedoch in ein Dateiobjekt Ihrer Wahl umleiten:

>>> with open("hello.txt", mode="w") as text_file:
...     print("Hello, World!", file=text_file)
...

Dieses Code-Snippet überschreibt Ihre vorhandene hello.txt-Datei aus dem vorherigen Abschnitt und schreibt den Satz "Hello, World!" hinein.

Schließlich haben Sie noch das Argument flush, das mit der Datenpufferung zu tun hat. Standardmäßig puffert Python die Aufrufe von print() in einem RAM-Datenpuffer. Dadurch kann Python weniger Systemaufrufe für Schreibvorgänge durchführen, indem es Zeichen im Puffer stapelt und sie alle auf einmal mit einem einzigen Systemaufruf schreibt.

Sie können das Argument flush auf True setzen, wenn Sie möchten, dass die Ausgabe Ihres Codes in Echtzeit angezeigt wird. Wenn Sie flush auf dem Standardwert False belassen, puffert Python die Ausgabe und diese Ausgabe wird erst angezeigt, wenn der Datenpuffer voll ist oder wenn Ihr Programm beendet ist Ausführung.

Ein cooles Beispiel für die Verwendung von flush ist die Erstellung eines Fortschrittsbalkens für eine CLI-Anwendung. Betrachten Sie die folgende Funktion:

def progress(percent=0, width=30):
    end = "" if percent < 100 else "\n"
    left = width * percent // 100
    right = width - left
    print(
        "\r[",
        "#" * left,
        " " * right,
        "]",
        f" {percent:.0f}%",
        sep="",
        end=end,
        flush=True,
    )

Diese Funktion generiert einen horizontalen Fortschrittsbalken, indem sie das Argument flush nutzt. So können Sie es in Ihrem Code verwenden:

>>> from time import sleep
>>> from progress import progress

>>> for percent in range(101):
...     sleep(0.2)
...     progress(percent)
...
[###########                   ] 38%

Diese Schleife ruft progress() mit aufeinanderfolgenden hypothetischen Fortschrittswerten auf. Die Ausgabe jedes Aufrufs wird geleert und der Fortschrittsbalken wird in derselben Zeile angezeigt.

Formatierungszeichenfolgen: format()

Python verfügt über einige praktische Tools zur String-Interpolation und -Formatierung, darunter F-Strings und die Methode str.format(). Diese Tools nutzen die String-Formatierungs-Minisprache von Python, die es Ihnen ermöglicht, Ihre Strings mithilfe einer speziellen Syntax gut zu formatieren.

Die integrierte Funktion format() ist ein weiteres Tool, mit dem Sie Werte formatieren können. Die Funktion hat die folgende Signatur:

format(value, format_spec="")

Die Funktion konvertiert value in eine formatierte Darstellung. Um das gewünschte Format zu definieren, können Sie das Argument format_spec verwenden, das eine Zeichenfolge akzeptiert, die der in der Minisprache zur Zeichenfolgenformatierung definierten Syntax folgt. Das Argument format_spec ist standardmäßig eine leere Zeichenfolge, wodurch die Funktion den übergebenen Wert zurückgibt.

Betrachten Sie die folgenden Beispiele für die Verwendung der Funktion format():

>>> import math
>>> from datetime import datetime

>>> format(math.pi, ".4f")  # Four decimal places
'3.1416'

>>> format(math.pi, "e")  # In scientific notation
'3.141593e+00'

>>> format(1000000, ",.2f")  # Thousand separators
'1,000,000.00'

>>> format("Header", "=^30")  # Centered and filled
'============Header============'

>>> format(datetime.now(), "%a %b %d, %Y")  # Date
'Mon Jul 1, 2024'

In diesen Beispielen haben Sie verschiedene Formatspezifizierer verwendet. Der Spezifizierer ".4f" formatiert den Eingabewert als Gleitkommazahl mit vier Dezimalstellen. Mit dem Spezifizierer "e" können Sie den Eingabewert in wissenschaftlicher Notation formatieren.

Mit dem Formatbezeichner ",.2f" können Sie eine Zahl mit Kommas als Tausendertrennzeichen und zwei Dezimalstellen formatieren, was ein geeignetes Format für Währungswerte ist. Anschließend verwenden Sie den Spezifizierer "=^30", um die Zeichenfolge "Header" zentriert in einer Breite von 30 Zeichen mit dem Gleichheitszeichen zu formatieren als Füllfigur. Schließlich verwenden Sie den "%a %b %d, %Y", um ein Datum zu formatieren.

Arbeiten mit Klassen, Objekten und Attributen

Python unterstützt objektorientierte Programmierung (OOP) mit Klassen, Typen, Vererbung und vielen anderen verwandten Funktionen. In Python ist alles ein Objekt. Das OOP-Paradigma ist also der Kern der Sprache selbst.

Sie verfügen über mehrere integrierte Funktionen, die Sie bei verschiedenen Aufgaben im Zusammenhang mit Klassen, Typen, Attributen, Methoden, Vererbung und anderen OOP-bezogenen Konzepten unterstützen.

Hier ist eine Zusammenfassung der OOP-bezogenen integrierten Funktionen von Python:

property()

Gibt einen Eigenschaftswert einer Klasse zurück

classmethod()

Gibt eine Klassenmethode zurück

staticmethod()

Gibt eine statische Methode zurück

getattr()

Gibt den Wert eines benannten Attributs eines Objekts zurück

setattr()

Legt den Wert eines benannten Attributs eines Objekts fest

delattr()

Löscht ein Attribut aus einem Objekt

hasattr()

Gibt True zurück, wenn ein Objekt ein bestimmtes Attribut hat

type()

Gibt den Typ eines Objekts zurück oder ermöglicht die dynamische Erstellung neuer Klassen

isinstance()

Bestimmt, ob ein Objekt eine Instanz einer bestimmten Klasse ist

issubclass()

Bestimmt, ob eine Klasse eine Unterklasse einer bestimmten Klasse ist

callable()

Gibt True zurück, wenn ein Objekt aufrufbar zu sein scheint

super()

Gibt ein Proxy-Objekt zurück, das Methodenaufrufe an eine übergeordnete oder Geschwisterklasse delegiert

object()

Erstellt ein neues merkmalsloses Objekt

In den folgenden Abschnitten erfahren Sie mehr über alle diese Funktionen und wie Sie sie in Ihrem objektorientierten Python-Code verwenden.

Gebäudeeigenschaften: property()

Mit der in Python integrierten Funktion property() können Sie verwaltete Attribute in Ihren Klassen erstellen. Verwaltete Attribute, auch Eigenschaften genannt, verfügen über einen zugeordneten Wert und eine interne Implementierung oder ein funktionsähnliches Verhalten.

Um dies anhand eines Beispiels zu veranschaulichen, nehmen wir an, dass Sie eine Point-Klasse erstellen möchten. In Python beginnen Sie etwa mit Folgendem:

>>> class Point:
...     def __init__(self, x, y):
...         self.x = x
...         self.y = y
...

>>> point = Point(42, 21)

>>> point.x
42
>>> point.y
21

>>> point.x = 0
>>> point.x
0

In dieser Klasse definieren Sie zwei Attribute, .x und .y, um die Koordinaten des Punkts darzustellen. Mithilfe der Punktnotation können Sie direkt auf die Attribute zugreifen und diese aktualisieren. Von nun an sind beide Attribute Teil der öffentlichen API Ihrer Klasse.

Angenommen, Sie müssen zusätzlich zu .x und .y eine Validierungslogik hinzufügen. Beispielsweise müssen Sie möglicherweise die Eingabewerte für beide Attribute validieren. Wie würden Sie das machen? In Programmiersprachen wie Java oder C++ würden Sie die Getter- und Setter-Methoden verwenden, die in Python übersetzt etwa so aussehen könnten:

class Point:
    def __init__(self, x, y):
        self.set_x(x)
        self.set_y(y)

    def get_x(self):
        return self._x

    def set_x(self, x):
        self._x = self.validate(x)

    def get_y(self):
        return self._y

    def set_y(self, y):
        self._y = self.validate(y)

    def validate(self, value):
        if not isinstance(value, int | float):
            raise ValueError("coordinates must be numbers")
        return value

In dieser neuen Implementierung von Point haben Sie .x und .y in nicht öffentliche Attribute umgewandelt, indem Sie ihren Namen Unterstriche vorangestellt haben Jetzt sind ._x und ._y. Anschließend definieren Sie Getter- und Setter-Methoden für beide Attribute. In den Setter-Methoden .set_x() und .set_y() fügen Sie die in der Methode .validate() definierte Validierungslogik ein.

Jetzt müssen Sie die Klasse wie im folgenden Code verwenden:

>>> from point_v1 import Point

>>> point = Point(42, 21)

>>> point.get_x()
42
>>> point.get_y()
21

>>> point.set_x(0)
>>> point.get_x()
0
>>> point.set_y("7")
Traceback (most recent call last):
    ...
ValueError: coordinates must be numbers

Ihre Klasse funktioniert nach dem Update anders. Anstatt direkt auf die Attribute .x und .y zuzugreifen, müssen Sie die Getter- und Setter-Methoden verwenden. Die Validierungslogik funktioniert, was großartig ist, aber Sie haben die API Ihrer Klasse beschädigt. Ihre Benutzer können beispielsweise Folgendes nicht tun:

>>> point.x
Traceback (most recent call last):
    ...
AttributeError: 'Point' object has no attribute 'x'

Alte Benutzer Ihrer Klasse werden überrascht sein, dass ihr Code nach dem Update auf Ihre neue Version von Point fehlerhaft ist. Wie können Sie also ein solches Problem vermeiden? Der Pythonic-Ansatz besteht darin, öffentliche Attribute in Eigenschaften umzuwandeln, anstatt Getter- und Setter-Methoden zu verwenden.

Für diese Konvertierung können Sie die integrierte Funktion property() verwenden. So können Sie die API Ihrer Point-Klasse unverändert lassen:

class Point:
    def __init__(self, x, y):
        self.x = x
        self.y = y

    @property
    def x(self):
        return self._x

    @x.setter
    def x(self, value):
        self._x = self.validate(value)

    @property
    def y(self):
        return self._y

    @y.setter
    def y(self, value):
        self._y = self.validate(value)

    def validate(self, value):
        if not isinstance(value, int | float):
            raise ValueError("coordinates must be numbers")
        return value

Point sieht jetzt etwas anders aus. Es gibt keine formalen Getter- und Setter-Methoden. Stattdessen gibt es einige Methoden, die mit @property dekoriert sind. Ja, die integrierte Funktion property() wird hauptsächlich als Dekorator verwendet.

Die Methoden, die Sie mit @property dekorieren, entsprechen Getter-Methoden. In der Zwischenzeit sind die Methoden, die Sie mit dem Namen des Getters und .setter() versehen, den Setter-Methoden äquivalent. Das Coole an Eigenschaften ist, dass Sie die Attribute weiterhin als reguläre Attribute verwenden können:

>>> from point_v2 import Point

>>> point = Point(42, 21)

>>> point.x
42
>>> point.y
21

>>> point.x = 0
>>> point.x
0

>>> point.x = "7"
Traceback (most recent call last):
    ...
ValueError: coordinates must be numbers

Indem Sie reguläre Attribute in Eigenschaften umwandeln, können Sie ihnen funktionsähnliches Verhalten hinzufügen, ohne die Fähigkeit zu verlieren, sie als reguläre Attribute zu verwenden. Eigenschaften ersparen Ihnen die Einführung bahnbrechender Änderungen in der öffentlichen API Ihres Codes, sodass Sie den Code Ihrer Benutzer nicht beschädigen.

Erstellen von Klassen und statischen Methoden: classmethod() und staticmethod()

Mit Klassen können Sie wiederverwendbare Codeteile definieren, die Daten und Verhalten in einer einzigen Entität kapseln. Normalerweise speichern Sie Daten in Attributen, bei denen es sich um Variablen handelt, die innerhalb von Klassen definiert sind. Wenn es um Verhalten geht, verwenden Sie Methoden, bei denen es sich um in Klassen definierte Funktionen handelt.

In Python gibt es drei verschiedene Arten von Methoden:

  1. Instanzmethoden, die das aktuelle Objekt als erstes Argument verwenden
  2. Klassenmethoden, die die aktuelle Klasse als erstes Argument verwenden
  3. Statische Methoden, die weder die aktuelle Instanz noch die aktuelle Klasse als Argumente verwenden

Instanzmethoden müssen die aktuelle Instanz als Argument verwenden. Konventionell heißt dieses Argument in Python self.

Um eine Klassenmethode zu erstellen, müssen Sie die Methode mit dem Dekorator @classmethod dekorieren. Ebenso müssen Sie zum Erstellen einer statischen Methode die Methode mit dem Dekorator @staticmethod dekorieren. Beide Dekoratoren sind Teil der integrierten Funktionen von Python.

Ein häufiger Anwendungsfall für Klassenmethoden besteht darin, mehrere Konstruktoren für eine Klasse bereitzustellen. Um zu veranschaulichen, wie eine Klassenmethode geschrieben wird, nehmen wir an, dass Sie eine Point-Klasse benötigen, die Sie entweder mit kartesischen oder polaren Koordinaten erstellen können. In dieser Situation können Sie etwa Folgendes tun:

import math

class Point:
    def __init__(self, x, y):
        self.x = x
        self.y = y

    @classmethod
    def from_polar(cls, distance, angle):
        return cls(
            x=distance * math.cos(math.radians(angle)),
            y=distance * math.sin(math.radians(angle)),
        )

In diesem Beispiel ist die Methode .from_polar() eine Klassenmethode. Als erstes Argument wird die aktuelle Klasse verwendet, die Sie normalerweise gemäß der Konvention cls nennen. Die Methode gibt eine neue Instanz der Klasse zurück, indem sie die kartesischen Koordinaten aus den Polarkoordinaten berechnet.

So können Sie diese Methode in der Praxis anwenden:

>>> from point import Point

>>> point = Point.from_polar(20, 15)

>>> point.y
5.176380902050415
>>> point.x
19.318516525781366

In diesem Codeausschnitt erstellen Sie eine neue Point-Instanz mithilfe der Klassenmethode .from_polar(). Im Beispiel rufen Sie die Methode für die Klasse und nicht für eine Instanz auf, um zu signalisieren, dass es sich um eine Klassenmethode handelt. Sie können eine Klassenmethode auch für eine Instanz der sie enthaltenden Klasse aufrufen.

Der dritte Methodentyp ist die statische Methode. Eine statische Methode verwendet nicht die aktuelle Instanz oder Klasse als Argumente. Diese Methoden ähneln regulären Funktionen, die Sie der Einfachheit halber in eine bestimmte Klasse aufnehmen möchten. Funktionell könnten sie auch als reguläre Funktionen in einem Modul definiert werden.

Betrachten Sie beispielsweise die folgende Formatter-Klasse:

class Formatter:
    @staticmethod
    def as_currency(value):
        return f"${value:,.2f}"

    @staticmethod
    def as_percent(value):
        return f"{value:.2%}"

Diese Klasse definiert zwei statische Methoden. Die erste Methode nimmt einen numerischen Wert und formatiert ihn als Währungswert. Die zweite Methode nimmt einen numerischen Wert und drückt ihn in Prozent aus. Sie hätten diese Methoden als reguläre Funktionen auf Modulebene definieren können. Sie haben sie jedoch in einer Klasse definiert, um sie bequem nach ihrer Verwendung zu gruppieren.

Sie können diese Klasse wie in den folgenden Beispielen verwenden:

>>> from formatting import Formatter

>>> Formatter.as_currency(1000)
'$1,000.00'

>>> Formatter.as_percent(0.75)
'75.00%'

>>> formatter = Formatter()
>>> formatter.as_currency(1000)
'$1,000.00'

>>> formatter.as_percent(0.8)
'80.00%'

Sie können statische Methoden verwenden, indem Sie sie für die Klasse oder eine ihrer Instanzen aufrufen. In diesem Beispiel fungiert die Klasse Formatter als Namespace, in dem Sie der Einfachheit halber verwandte Methoden definieren. Sie können jedoch das gleiche Ergebnis erzielen, indem Sie die Methoden als Funktionen auf Modulebene definieren.

Verwalten von Attributen: getattr(), setattr() und delattr()

Manchmal müssen Sie möglicherweise auf Attribute Ihrer Objekte in Python zugreifen, diese festlegen oder löschen. In den meisten Fällen können Sie diese Operationen direkt mit der Punktnotation, dem Zuweisungsoperator und der del-Anweisung ausführen.

In anderen Situationen kennen Sie die Namen der Attribute erst zur Laufzeit und können daher nicht mit der regulären Syntax darauf zugreifen. In diesen Fällen können Sie die integrierten Funktionen getattr(), setattr() und delattr() verwenden. Diese Funktionen haben die folgenden Signaturen:

getattr(object, name)
getattr(object, name, default)

setattr(object, name, value)

delattr(object, name)

In allen Fällen muss das Argument object eine Instanz einer vorhandenen Klasse annehmen. Ebenso muss name der Name eines Attributs oder einer Methode als Zeichenfolge sein.

In der zweiten Signatur von getattr() ist das Argument default ein optionaler Wert, den Sie erhalten, wenn das gewünschte Attribut im Zielobjekt nicht vorhanden ist.

In der Signatur von setattr() muss das Argument value den neuen Wert enthalten, den Sie einem bestimmten Argument zuweisen möchten.

Um zu veranschaulichen, wie diese Funktionen funktionieren, betrachten Sie die folgende Klasse:

class Person:
    def __init__(self, name, age):
        self.name = name
        self.age = age

Diese Klasse verfügt über zwei Instanzattribute: .name und .age. So können Sie auf die Attribute zugreifen, sie festlegen oder löschen, indem Sie ihre Namen als Zeichenfolgen verwenden:

>>> from person import Person

>>> jane = Person("Jane", 25)

>>> getattr(jane, "name")
'Jane'
>>> getattr(jane, "age")
25

In diesen Beispielen verwenden Sie getattr(), um die in .name und .age gespeicherten Werte abzurufen. Das erste Argument dieser Funktion ist das Objekt, von dem Sie ein Attribut abrufen müssen. Das zweite Argument ist der Name des Attributs als String.

Sagen Sie nun, dass Sie Janes Alter aktualisieren möchten. Sie können dies mit der Funktion setattr() tun:

>>> setattr(jane, "age", 26)
>>> jane.age
26

Anschließend verwenden Sie die Funktion setattr(), um dem Attribut .age einen neuen Wert zuzuweisen. Diese Funktion benötigt drei Argumente: das Objekt, den Namen des Attributs und den neuen Wert.

Schließlich können Sie die integrierte Funktion delattr() verwenden, um ein Attribut aus einem bestimmten Objekt zu löschen:

>>> delattr(jane, "age")
>>> jane.age
Traceback (most recent call last):
    ...
AttributeError: 'Person' object has no attribute 'age'

Die Funktion delattr() verwendet das Objekt als erstes Argument und den Namen des Attributs als zweites Argument. Nach dem Aufruf der Funktion wird beim Versuch, auf .age zuzugreifen, eine AttributeError-Ausnahme ausgelöst.

In der Praxis sind die integrierten Funktionen getattr(), setattr() und delattr() praktisch, wenn Sie Attribute bearbeiten müssen ihre Namen als Strings verwenden. Angenommen, Sie möchten eine FileProcessor-Klasse zum Lesen und Schreiben von CSV- und JSON-Dateien erstellen. In dieser Situation können Sie dedizierte Klassen für die Verarbeitung jedes Dateityps haben:

import csv
import json

class CSVProcessor:
    def __init__(self, filename):
        self.filename = filename

    def read(self):
        with open(self.filename, encoding="utf-8", newline="") as file:
            return list(csv.DictReader(file))

    def write(self, data):
        with open(
            self.filename, mode="w", encoding="utf-8", newline=""
        ) as file:
            writer = csv.DictWriter(file, fieldnames=data[0].keys())
            writer.writeheader()
            writer.writerows(data)

class JSONProcessor:
    def __init__(self, filename):
        self.filename = filename

    def read(self):
        with open(self.filename, encoding="utf-8") as file:
            return json.load(file)

    def write(self, data):
        with open(self.filename, mode="w", encoding="utf-8") as file:
            json.dump(data, file, indent=2)

In dieser Datei processors.py definieren Sie zwei Klassen, die CSV- bzw. JSON-Dateien verarbeiten können. Beide Klassen verfügen über die Methoden .read() und .write(). Diese Klassen sehen gut aus, aber jetzt müssen Sie sie über Ihre FileProcessor-Klasse nutzbar machen.

Um die Klasse FileProcessor zu schreiben, können Sie eine Technik namens Delegation verwenden, die darin besteht, das Attribut oder die Methode eines Objekts im Kontext eines anderen Objekts auszuwerten. So können Sie dies in Python tun:

# ...

class FileProcessor:
    def __init__(self, filename, processor):
        self.filename = filename
        self.processor = processor(filename)

    def __getattr__(self, attr):
        return getattr(self.processor, attr)

In dieser Klasse definieren Sie die spezielle Methode .__getattr__(). Diese Methode unterstützt Attributzugriffsoperationen in Python-Klassen. In der Methodendefinition verwenden Sie die Funktion getattr(), um auf Attribute und Methoden des bereitgestellten Prozessorobjekts zuzugreifen.

In der Praxis verwenden Sie die Kombination der Methode .__getattr__() und der Funktion getattr(), um die Delegierung zu implementieren. Die Klasse FileProcessor delegiert die Dateiverarbeitung an die konkrete Prozessorklasse, die Sie während der Instanziierung übergeben.

So können Sie die Klasse FileProcessor in Ihrem Code verwenden:

>>> from processors import FileProcessor

>>> file_proc = FileProcessor("products.csv", CSVProcessor)
>>> file_proc.read()
[
    {'product': 'Laptop', 'price': '1200', 'sold_units': '30'},
    {'product': 'Phone', 'price': '700', 'sold_units': '50'},
    {'product': 'Tablet', 'price': '450', 'sold_units': '100'},
    {'product': 'Desktop', 'price': '1000', 'sold_units': '20'},
    {'product': 'Monitor', 'price': '300', 'sold_units': '50'}
]

In diesem Code erstellen Sie eine FileProcessor-Instanz, um eine CSV-Datei mit dem CSVProcessor zu verarbeiten. Auch wenn die Instanz keine Methode .read() hat, können Sie die Methode aufgrund der Delegierungstechnik aufrufen, die auf der Funktion getattr() basiert.

Auf Attribute prüfen: hasattr()

Eine weitere integrierte Funktion, die eng mit Attributen und Methoden zusammenhängt, ist die Funktion hasattr(). Mit dieser Funktion können Sie überprüfen, ob ein bestimmtes Objekt ein bestimmtes Attribut oder eine bestimmte Methode hat. Die Funktion hat die folgende Signatur:

hasattr(object, name)

In dieser Signatur kann das Argument object jedes Python-Objekt annehmen, während das Argument name den Namen eines Attributs als String enthalten sollte. Diese Funktion ist ein Prädikat, das True zurückgibt, wenn das Objekt ein Attribut mit dem angegebenen Namen hat, andernfalls False.

In der Praxis können Sie diese Funktion verwenden, um zu prüfen, ob ein Objekt über ein bestimmtes Attribut oder eine bestimmte Methode verfügt, bevor Sie versuchen, es zu verwenden. Angenommen, Sie haben die folgenden Klassen:

class Duck:
    def fly(self):
        print("The duck is flying")

    def swim(self):
        print("The duck is swimming")

class Pigeon:
    def fly(self):
        print("The pigeon is flying")

Diese Klassen repräsentieren zwei verschiedene Vögel. Beide Vögel sind flugfähig, aber nur die Ente kann schwimmen. Angenommen, Sie möchten sie in einer Schleife wie der folgenden verwenden:

>>> from birds import Duck, Pigeon

>>> birds = [Duck(), Pigeon()]

>>> for bird in birds:
...     bird.fly()
...     bird.swim()
...
The duck is flying
The duck is swimming
The pigeon is flying
Traceback (most recent call last):
    ...
AttributeError: 'Pigeon' object has no attribute 'swim'

Diese Schleife funktioniert für die Instanz von Duck. Allerdings wird eine AttributeError-Ausnahme ausgelöst, wenn Sie .swim() für eine Pigeon-Instanz aufrufen, da die Klasse diese Methode nicht hat. Um diesen Fehler zu vermeiden, können Sie mit der Funktion hasattr() prüfen, ob die Methode existiert, bevor Sie sie aufrufen:

>>> for bird in birds:
...     bird.fly()
...     if hasattr(bird, "swim"):
...         bird.swim()
...
The duck is flying
The duck is swimming
The pigeon is flying

Ihr Code schlägt jetzt nicht fehl, da Sie die Funktion hasattr() verwendet haben, um sicherzustellen, dass der aktuelle Vogel über die Methode .swim() verfügt, bevor Sie ihn aufrufen.

Erstellen und Überprüfen von Typen: type(), isinstance() und issubclass()

Python ist eine dynamisch typisierte Sprache, was bedeutet, dass Python Typen nur während der Codeausführung prüft und sich der Typ einer Variablen im Laufe ihrer Lebensdauer ändern kann. Aufgrund dieser Sprachfunktion müssen Sie möglicherweise den Typ eines Objekts explizit überprüfen, bevor Sie es verwenden, damit Ihr Code nicht fehlschlägt.

Um den Typ eines bestimmten Objekts zu ermitteln, können Sie die integrierte Funktion type() verwenden:

>>> type(42)
<class 'int'>

>>> type(2.75)
<class 'float'>

>>> type("Hello")
<class 'str'>

Wenn Sie type() mit einer beliebigen Python-Klasse als Argument aufrufen, erhalten Sie den Typ des Objekts, den Sie auch als Klasse des Objekts bezeichnen können. In diesem Beispiel rufen Sie type() mit einer Ganzzahl als Argument auf und erhalten die Klasse int als Antwort. Dann verwenden Sie type() mit einer Gleitkommazahl und erhalten die Klasse float und so weiter.

Wenn Sie den Typ eines Objekts mit type() überprüfen möchten, können Sie etwa Folgendes tun:

>>> type(42) == int
True
>>> type(42) == float
False

Diese Art der Verwendung von type() funktioniert. Dies ist jedoch nicht der empfohlene Ansatz. Sie werden gleich mehr über die Typprüfung erfahren. Zunächst lernen Sie weiterhin die Grundlagen von type(). Zum Auftakt hier die Signaturen der Funktion:

type(object)
type(name, bases, dict, **kwds)

Sie haben bereits die erste Signatur verwendet. In dieser Signatur stellt das Argument object ein beliebiges Python-Objekt dar.

Die zweite Signatur ist etwas komplizierter. Sie verwenden diese Signatur, um dynamisch neue Klassen zu erstellen, anstatt den Typ eines Objekts zu bestimmen. Hier ist eine Zusammenfassung der Argumente und ihrer Bedeutung:

name

Der Name der Klasse

base

Ein Tupel, das die Basisklassen enthält

dict

Ein Wörterbuch mit Attributen und Methoden, die im Klassenkörper definiert sind

**kwds

Zusätzliche Schlüsselwortargumente, die an den Metaklassenkonstruktor übergeben werden

Wenn Sie type() mit diesen Argumenten verwenden, können Sie Klassen dynamisch erstellen. Auf diese Weise ist type() eine dynamische Form der class-Anweisung. Betrachten Sie das folgende Spielzeugbeispiel:

>>> def greet(self):
...     print("Hello, World!")
...

>>> DemoClass = type("DemoClass", (), {"value": 42, "greet": greet})
>>> DemoClass.value
42
>>> instance = DemoClass()
>>> instance.value
42
>>> instance.greet()
Hello, World!

>>> dir(instance)
[
    '__class__',
    '__delattr__',
    '__dict__',
    ...
    'greet',
    'value'
]

In diesem kurzen Beispiel verwenden Sie type(), um eine Demoklasse zu erstellen, die automatisch von object erbt, da das base-Tupel leer ist. Die neue Klasse verfügt über eine Methode namens .greet(), die Sie zuvor definiert haben. Es verfügt außerdem über ein Klassenattribut namens .value, das Sie auf 42 setzen.

Für Attribute sollten Sie den Namen des Attributs als Zeichenfolge und den Wert des Attributs angeben. Bei Methoden sollten Sie den Namen der Methode als Zeichenfolge und als Methodenobjekt angeben, also eine Methode ohne die aufrufenden Klammern. Beachten Sie, dass Instanzmethoden wie .greet() das aktuelle Objekt als Argument verwenden müssen, das Sie normalerweise self nennen.

Nehmen wir als realistischeres Beispiel an, dass Sie eine Funktion schreiben möchten, mit der Sie Klassen dynamisch aus verschiedenen Datenschemata erstellen können. In dieser Situation können Sie etwa Folgendes tun:

def create_class(name, custom_members):
    def __init__(self, **kwargs):
        self.__dict__.update(kwargs)

    def __repr__(self):
        return f"{name}({self.__dict__})"

    class_members = {
        "__init__": __init__,
        "__repr__": __repr__,
    }
    class_members.update(custom_members)

    return type(name, (), class_members)

In diesem Code erstellen Sie eine Funktion, die zwei Argumente akzeptiert. Das erste Argument, name, sollte eine Zeichenfolge sein, die einen gültigen Klassennamen angibt. Das zweite Argument, custom_members, sollte ein Wörterbuch mit Attributen und Methoden sein.

Anschließend definieren Sie eine innere Funktion namens .__init__(), die Sie als Klasseninitialisierer verwenden. Mit der Funktion .__repr__() können Sie eine Zeichenfolgendarstellung für die Objekte Ihrer Klasse bereitstellen.

Als Nächstes erstellen Sie ein Wörterbuch, um die Funktionen als Methoden für Ihre Klasse einzuschließen, und aktualisieren das Wörterbuch mit dem Inhalt von class_members, der vom Benutzer stammen sollte.

Schließlich verwenden Sie die Funktion type(), um die Klasse mit dem angegebenen Namen und dem Wörterbuch der Mitglieder zu generieren. Hier sind einige Beispiele für die Verwendung dieser Funktion:

>>> from factory import create_class

>>> User = create_class("User", {"name": "", "age": 0, "email": ""})
>>> Product = create_class(
...     "Product", {"name": "", "price": 0.0, "units": 0}
... )

>>> john = User(name="John", age=30, email="john@example.com")
>>> table = Product(name="Table", price=200.0, units=5)

>>> john.name
'John'
>>> john.age
30
>>> john.email
'john@example.com'

>>> table.name
'Table'
>>> table.price
200.0
>>> table.units
5

In diesem Codeausschnitt erstellen Sie zunächst zwei Klassen mit create_class(). Die erste Klasse repräsentiert Benutzer und die zweite repräsentiert Produkte. Beide verfügen über unterschiedliche Sätze von Instanzattributen.

Anschließend erstellen Sie konkrete Instanzen jeder Klasse mit den richtigen Werten für die Attribute. Schließlich greifen Sie über die Punktnotation auf die Attribute zu. Das ist großartig! Ihre Kurse funktionieren wie erwartet.

Die Funktion type() ist ein großartiges Werkzeug zum dynamischen Erstellen von Klassen. Obwohl Sie diese Funktion auch verwenden können, um den Typ eines Objekts zu überprüfen, ist das empfohlene Tool für die explizite Typprüfung die integrierte Funktion isinstance(), da sie Unterklassen berücksichtigt.

Die Signatur für isinstance() sieht wie folgt aus:

isinstance(object, classinfo)

In dieser Signatur stellt object jedes Python-Objekt dar, an dem Sie interessiert sind. Das Argument classinfo ist die Klasse oder die Klassen, gegen die Sie prüfen möchten. Dieses Argument kann ein einzelnes Klassenobjekt, ein Tupel von Klassenobjekten oder ein Union-Typ sein.

Betrachten Sie die folgenden Beispiele, in denen Sie isinstance() verwenden, um nach numerischen Werten zu suchen:

>>> isinstance(42, int)
True

>>> isinstance(42.0, (int, float))
True

>>> isinstance(42.0, int | float)
True

Im ersten Beispiel überprüfen Sie mit isinstance(), ob 42 eine Instanz der Klasse int ist. Im zweiten Beispiel überprüfen Sie mit isinstance(), ob 42.0 eine Instanz von int oder float ist . In diesem Beispiel verwenden Sie ein Tupel von Klassen, um das Argument classinfo bereitzustellen.

Schließlich führen Sie im dritten Beispiel die gleiche Prüfung durch wie im zweiten Beispiel. Dieses Mal verwenden Sie das Pipe-Zeichen (|), um einen Union-Typ mit int und float zu erstellen. Beachten Sie, dass isinstance() eine Prädikatfunktion ist, die True zurückgibt, wenn das Eingabeobjekt eine Instanz einer der bereitgestellten Klassen ist.

Die Funktion isinstance() berücksichtigt auch Unterklassen. Beispielsweise ist die Klasse bool eine Unterklasse von int. Wenn Sie also eine Instanz von bool mit int vergleichen, dann erhalten Sie als Ergebnis True:

>>> isinstance(False, int)
True

>>> type(False) == int
False

Da bool eine Unterklasse von int ist, gibt die Funktion isinstance() True zurück, wenn Sie einen booleschen Wert vergleichen die Klasse int. Beachten Sie, dass Sie, wenn Sie versuchen, eine ähnliche Prüfung mit type() durchzuführen, False erhalten, da type() keine Unterklassen berücksichtigt.

Es gibt eine weitere integrierte Funktion, die für die Typprüfung nützlich sein kann. Die Funktion heißt issubclass() und prüft, ob eine bestimmte Klasse eine Unterklasse einer anderen Klasse ist:

>>> issubclass(int, object)
True

>>> issubclass(bool, int)
True

>>> issubclass(int, float)
False

Im ersten Beispiel prüfen Sie, ob die Klasse int eine Unterklasse von object ist. In diesem Fall erhalten Sie True, da alle Python-Klassen von object abgeleitet sind. Anschließend prüfen Sie, ob bool eine Unterklasse von int ist, was, wie Sie bereits erfahren haben, auch zutrifft.

Im letzten Beispiel verwenden Sie issubclass(), um zu prüfen, ob int eine Unterklasse von float ist, was False ist .

Die Signatur von issubclass() lautet wie folgt:

issubclass(class, classinfo)

In diesem Fall ist das Argument class die Klasse, nach der Sie suchen möchten, während das Argument classinfo genauso funktioniert wie in isinstance() .

Auf aufrufbare Objekte prüfen: callable()

Ein Callable in Python ist jedes Objekt, das Sie bei Bedarf mithilfe eines Klammerpaars und einer Reihe von Argumenten aufrufen können. In Python umfassen aufrufbare Objekte Funktionen, Klassen, Methoden, Instanzen von Klassen mit einer .__call__()-Methode, Abschlüsse und Generatorfunktionen.

Manchmal müssen Sie möglicherweise wissen, ob ein Objekt aufrufbar ist, bevor Sie es in Ihrem Code aufrufen. Dazu können Sie die integrierte Funktion callable() verwenden, die ein Objekt als Argument akzeptiert und True zurückgibt, wenn das Objekt aufrufbar zu sein scheint. Andernfalls wird False zurückgegeben.

Hier sind einige Beispiele für die Verwendung von callable() mit einigen integrierten Objekten:

>>> callable(abs)
True
>>> callable(int)
True
>>> callable(list)
True

>>> callable(True)
False
>>> callable(None)
False

In den ersten drei Beispielen sind die Argumente für callable() allesamt Funktionen, sodass Sie als Ergebnis True erhalten. In den letzten beiden Beispielen verwenden Sie die Objekte True und None als Argumente. Diese Objekte sind nicht aufrufbar, daher erhalten Sie als Ergebnis False.

Nehmen wir als praktisches Beispiel an, dass Sie eine App erstellen müssen, die Befehle verarbeitet. Jeder Befehl sollte aufrufbar sein, sonst ist er ungültig. Um diese Bedingung zu überprüfen, können Sie callable() verwenden. Hier ist eine Spielzeugimplementierung:

class CommandProcessor:
    def __init__(self):
        self.commands = {}

    def register_command(self, command):
        if not callable(command):
            raise ValueError("command is not callable")
        self.commands[command.__name__] = command

    def execute_command(self, name, *args, **kwargs):
        if (command := self.commands.get(name)) is None:
            raise ValueError(f"command '{name}' not found")
        return command(*args, **kwargs)

In dieser Klasse verwendet die Methode .register_command() callable(), um zu prüfen, ob der Eingabebefehl ein aufrufbares Objekt ist. Wenn dies der Fall ist, registrieren Sie den Befehl als gültig. Als nächstes haben Sie die Methode .execute_command(), die den Befehl als aufrufbares Element ausführt.

Hier ist ein Beispiel für die Verwendung dieser Klasse:

>>> from commands import CommandProcessor

>>> command_processor = CommandProcessor()

>>> def add(a, b):
...     return a + b
...

>>> command_processor.register_command(add)
>>> command_processor.execute_command("add", 1, 2)
3

>>> subtract = 3 - 2
>>> command_processor.register_command(subtract)
Traceback (most recent call last):
    ...
ValueError: command is not callable

In diesem Beispiel erstellen Sie eine CommandProcessor-Instanz, um Befehle zu verarbeiten. Dann schreiben Sie add(), um es als Befehl zu verwenden. Da add() ein aufrufbares Objekt ist, können Sie es als gültigen Befehl registrieren und mit der Methode .execute_command() ausführen.

Schließlich definieren Sie die Variable subtract, um das Ergebnis einer Subtraktionsoperation zu speichern. Diese Variable ist nicht aufrufbar. Daher erhalten Sie eine ValueError-Ausnahme, wenn Sie ihn als Befehl registrieren.

Zugriff auf die Mitglieder des übergeordneten Elements: super()

Wenn Sie in Python-Klassen mit der Vererbung arbeiten, müssen Sie häufig auf die Attribute oder Methoden einer übergeordneten Klasse in einer Unterklasse zugreifen. Der pythonische Weg, dies zu tun, ist die Verwendung der integrierten Funktion super().

Ein häufiger Anwendungsfall für super() ist, wenn Sie eine Unterklasse einer vorhandenen Klasse erstellen müssen und eine geeignete Methode zum Initialisieren der Attribute der übergeordneten Klasse benötigen. Betrachten Sie die folgenden Klassen, die ein Rechteck und ein Quadrat darstellen:

class Rectangle:
    def __init__(self, length, width):
        self.length = length
        self.width = width

    def area(self):
        return self.length * self.width

    def perimeter(self):
        return 2 * (self.length + self.width)

class Square(Rectangle):
    def __init__(self, side):
        super().__init__(side, side)

In diesem Code definieren Sie eine Rectangle-Klasse mit zwei Attributen, .length und .width. Es verfügt außerdem über zwei Methoden zur Berechnung der Fläche und des Umfangs des Rechtecks. Als Nächstes definieren Sie die Klasse Square. Da es sich bei einem Quadrat um eine Art Rechteck mit gleichen Seiten handelt, ist es sinnvoll, Square als Unterklasse von Rectangle zu erstellen und die bereits implementierte Funktionalität wiederzuverwenden.

Im Square()-Konstruktor benötigen Sie nur ein einziges Argument, um die Seitenlänge darzustellen. Sie können dieses Argument verwenden, um die übergeordnete Klasse mit super() zu initialisieren, wie Sie es in der hervorgehobenen Zeile getan haben. Mit der Funktion super() erhalten Sie Zugriff auf die übergeordnete Klasse Rectangle. Sobald Sie Zugriff auf die Klasse haben, können Sie deren Methode .__init__() aufrufen, um die Attribute .length und .width mit dem Wert zu initialisieren der Seite.

Generische Objekte erstellen: object()

In Python erbt jede einzelne Klasse implizit von der Klasse object, die in die Sprache integriert ist. Mit anderen Worten: Die Klasse object ist die Basisklasse für jede Klasse in Python:

>>> issubclass(int, object)
True
>>> issubclass(float, object)
True
>>> issubclass(bool, object)
True
>>> issubclass(dict, object)
True

>>> class DemoClass:
...     pass
...
>>> issubclass(DemoClass, object)
True

Unabhängig davon, ob es sich bei der Klasse, die Sie in Betracht ziehen, um eine integrierte oder eine benutzerdefinierte Klasse handelt, erbt sie von object.

In manchen Situationen möchten Sie möglicherweise Instanzen der Klasse object erstellen. Dazu können Sie die integrierte Funktion object() verwenden, bei der es sich eigentlich um einen Klassenkonstruktor und nicht um eine Funktion handelt, die in der Python-Dokumentation jedoch zu den integrierten Funktionen zählt.

Die Funktion object() akzeptiert kein Argument und gibt ein neues funktionsloses Objekt zurück, das über die Methoden verfügt, die allen Python-Objekten gemeinsam sind. Im Gegensatz zu regulären Objekten verfügt das Objekt, das Sie durch den Aufruf von object() erhalten, nicht über ein .__dict__-Attribut, sodass Sie diesem Objekttyp keine Attribute dynamisch hinzufügen können :

>>> obj = object()
>>> dir(obj)
[
    '__class__',
    '__delattr__',
    '__dir__',
    ...
    '__str__',
    '__subclasshook__'
]
>>> obj.attr = "Some value"
Traceback (most recent call last):
    ...
AttributeError: 'object' object has no attribute 'attr'

In diesem Beispiel erstellen Sie ein neues funktionsloses Objekt, indem Sie object() aufrufen. Mit der integrierten Funktion dir() können Sie alle Methoden und Attribute auflisten, die dieses Objekt bereitstellt. Wenn Sie schließlich versuchen, Ihrem Objekt ohne Merkmale dynamisch ein Attribut hinzuzufügen, erhalten Sie eine AttributeError-Ausnahme.

In der Praxis können Sie die Funktion object() verwenden, wenn Sie eindeutige Sentinel-Werte erstellen möchten. Ein Sentinel-Wert ist ein eindeutiger Marker, mit dem Sie das Fehlen eines Werts kennzeichnen können. Sie können es auch als Bedingung zum Stoppen iterativer oder rekursiver Algorithmen verwenden.

Um zu veranschaulichen, wie mit object() ein Sentinel-Wert erstellt wird, betrachten Sie die folgende Circle-Klasse:

from time import sleep

SENTINEL = object()

class Circle:
    def __init__(self, radius):
        self.radius = radius
        self._diameter = SENTINEL

    @property
    def diameter(self):
        if self._diameter is SENTINEL:
            sleep(0.5)  # Simulate a costly computation
            self._diameter = self.radius * 2
        return self._diameter

In dieser Klasse haben Sie ein .radius-Attribut, das zum Zeitpunkt der Instanziierung einen Wert annimmt. Dann haben Sie ein nicht öffentliches Attribut namens ._diameter, das Sie mit der Konstante SENTINEL initialisieren. Um diese Konstante zu erstellen, verwenden Sie die Funktion object().

Schließlich haben Sie die Eigenschaft .diameter, die den Durchmesser aus dem angegebenen Radius berechnet. In diesem Beispiel verwenden Sie sleep() aus dem Modul time, um zu simulieren, dass das Ermitteln des Durchmessers ein kostspieliger Vorgang ist. Aufgrund des Berechnungsaufwands entscheiden Sie sich, den Durchmesser zwischenzuspeichern, sodass er ein einziges Mal während der Lebensdauer des Objekts berechnet wird.

Um zu überprüfen, ob der Durchmesser bereits berechnet wurde, vergleichen Sie seinen aktuellen Wert mit der SENTINEL-Konstante. In diesem Beispiel hätten Sie auch None als Sentinel-Wert verwenden können, da der Durchmesser eines Kreises wahrscheinlich keinen Nullwert annimmt. Wenn jedoch None ein gültiger Wert für das jeweilige Attribut sein kann, dann kann object() der richtige Weg sein.

Arbeiten mit Python-Bereichen

Python verwaltet, wie viele andere Programmiersprachen, das Konzept der Bereiche. Der Bereich bestimmt, wie Variablen und Namen in Ihrem Code gesucht werden. Es bestimmt die Sichtbarkeit einer Variablen oder eines Namens im Code.

Der Gültigkeitsbereich hängt von dem Ort ab, an dem Sie diese Variable erstellen. Die Bereiche von Python folgen einer Regel, die als LEGB-Regel bekannt ist. Die Buchstaben in diesem Akronym stehen für lokale, umschließende, globale und eingebaute Bereiche sowie diese Regel fasst die vier Bereiche zusammen, die Sie in Python finden.

Sie finden zwei integrierte Funktionen, die eng mit Bereichen in Python verknüpft sind. Diese Funktionen sind in der folgenden Tabelle aufgeführt:

locals()

Aktualisiert ein Wörterbuch, das die aktuelle lokale Symboltabelle darstellt, und gibt es zurück

globals()

Gibt ein Wörterbuch zurück, das die aktuelle globale Symboltabelle darstellt

In den folgenden Abschnitten lernen Sie die Grundlagen dieser Funktionen kennen und erfahren, wie Sie sie in Ihrem Python-Code verwenden, um einige Aspekte Ihrer Namensbereiche zu verwalten.

Überprüfen und Aktualisieren eines lokalen Bereichs: locals()

Der lokale Bereich ist der Funktionsbereich, da er den Hauptteil der Funktion umfasst. Jedes Mal, wenn Sie eine Funktion aufrufen, erstellt Python einen neuen lokalen Bereich für diese Funktion. Standardmäßig existieren Argumente und Namen, die Sie im Hauptteil einer Funktion zuweisen, nur innerhalb des lokalen Bereichs, den Python erstellt, wenn Sie die Funktion aufrufen. Wenn die Funktion zurückkehrt, verschwindet der lokale Gültigkeitsbereich und die Namen werden vergessen.

Wenn Sie jemals den Status Ihres aktuellen lokalen Bereichs überprüfen müssen, können Sie die integrierte Funktion locals() verwenden:

>>> def add(a, b):
...     result = a + b
...     print(locals())
...     return result
...

>>> add(2, 5)
{'a': 2, 'b': 5, 'result': 7}
7

In dieser Funktion verwenden Sie zwei Argumente, a und b. Diese Argumente sind lokal für add(), was bedeutet, dass Sie nur innerhalb der Funktion auf sie zugreifen und sie verwenden können. Anschließend erstellen Sie eine lokale Variable mit dem Namen result, die Sie als temporäre Variable zum Speichern der Berechnungsergebnisse verwenden. Der Aufruf von locals() gibt ein Wörterbuch zurück, das die Namen und Werte aller dieser Variablen enthält.

Beachten Sie, dass locals() die Bereichsinformationen nur bis zu dem Punkt erfasst, an dem Sie sie aufrufen:

>>> def add(a, b):
...     print(locals())
...     result = a + b
...     return result
...

>>> add(2, 5)
{'a': 2, 'b': 5}
7

In dieser Variante von add() rufen Sie locals() am Anfang der Funktion auf. Sie erhalten also nur die Argumente im Ergebniswörterbuch. Dies liegt daran, dass beim Aufruf von locals() die Variable result noch nicht definiert wurde.

Überprüfen und Aktualisieren des globalen Bereichs: globals()

Der globale Bereich ist ein weiterer wichtiger Bereich in Python. Es handelt sich um den Bereich auf Modulebene, mit dem Sie globale Variablen oder Namen definieren können. Sie können von überall in Ihrem Code auf globale Namen zugreifen und diese ändern.

Um die Variablen und Namen, die sich in Ihrem aktuellen globalen Bereich befinden, zu überprüfen und zu aktualisieren, können Sie die integrierte Funktion globals() verwenden. Wenn Sie beispielsweise eine neue REPL-Sitzung starten und globals() aufrufen, erhalten Sie eine Ausgabe wie die folgende:

>>> globals()
{
    '__name__': '__main__',
    '__doc__': None,
    ...
    '__builtins__': <module 'builtins' (built-in)>
}

Wenn Sie eine REPL-Sitzung starten, lädt der Interpreter standardmäßig mehrere Namen und Objekte in Ihren globalen Bereich. Beispielsweise enthält das Objekt __name__ den Namen des aktuellen Moduls, der "__main__" lautet, wenn Sie sich in einem ausführbaren Modul befinden. Wenn Sie sich in einem importierten Modul befinden, enthält diese Variable den Namen des Moduls.

Dann haben Sie den Namen __doc__, der die Dokumentzeichenfolge des Moduls enthält, sofern angegeben. Sie werden auch mehrere andere Namen haben. Schließlich haben Sie den Namen __builtins__, der den Namespace enthält, in dem integrierte Namen definiert sind. Dies ist ein spezielles Modul, das alle in diesem Tutorial behandelten integrierten Funktionen sowie mehrere andere integrierte Objekte, wie z. B. Ausnahmen, enthält.

Wenn Sie in Ihrer REPL-Sitzung mit der Definition von Variablen und Funktionen beginnen, werden diese Namen dem Wörterbuch hinzugefügt, das globals() zurückgibt:

>>> language = "Python"
>>> number = 42
>>> def greet():
...     print("Hello, World!")
...
>>> class Demo:
...     pass
...

>>> globals()
{
    ...
    '__builtins__': <module 'builtins' (built-in)>,
    'language': 'Python',
    'number': 42,
    'greet': <function greet at 0x100984040>,
    'Demo': <class '__main__.Demo'>
}

In diesem Beispiel definieren Sie zwei Variablen, eine Funktion und eine Klasse. Wenn Sie globals() aufrufen, erhalten Sie die Namen aller dieser Objekte am Ende des resultierenden Wörterbuchs.

Das Wörterbuch, das globals() zurückgibt, ist ein beschreibbares Wörterbuch. Sie können diese Funktion nutzen, wenn Sie den Inhalt des globalen Bereichs manuell ändern oder aktualisieren müssen. Ein häufiger Anwendungsfall für diese Funktion ist das Laden von Konfigurationsparametern aus einer Datei.

Angenommen, Sie verfügen über die folgende JSON-Datei mit einigen Konfigurationswerten für Ihre Datenbankverbindung:

{
    "DATABASE_URL": "postgres://user:pass@localhost/dbname",
    "DEBUG_MODE": true,
    "MAX_CONNECTIONS": 10
}

Sie müssen eine Funktion schreiben, die diese Datei lädt und die bereitgestellten Konfigurationsparameter zu Ihrem aktuellen globalen Bereich hinzufügt. Hier ist eine mögliche Implementierung dieser Funktion:

import json

def load_config(config_file):
    with open(config_file) as file:
        config = json.load(file)

    globals().update(config)

In dieser Funktion öffnen Sie zunächst die Konfigurationsdatei und laden ihren Inhalt in ein Wörterbuch namens config. Anschließend aktualisieren Sie das Wörterbuch, das globals() zurückgibt, mit dem Inhalt von config.

So funktioniert die obige Funktion:

>>> from config import load_config

>>> load_config("config.json")
>>> globals()
{
    ...
    'DATABASE_URL': 'postgres://user:pass@localhost/dbname',
    'DEBUG_MODE': True,
    'MAX_CONNECTIONS': 10
}

>>> MAX_CONNECTIONS
10

Nachdem Sie load_config() mit der Datei config.json als Argument aufgerufen haben, werden die Konfigurationsparameter als Konstanten in Ihren globalen Bereich geladen. Jetzt können Sie diese Konstanten direkt in Ihrem Code verwenden.

Objekte introspizieren

In der Programmierung bezeichnet Typintrospektion die Fähigkeit eines Programms, den Typ und die Eigenschaften eines Objekts zur Laufzeit zu überprüfen. Alles in Python ist ein Objekt, daher ist die Möglichkeit, Typen und Eigenschaften zur Laufzeit untersuchen zu können, ein wertvoller Vorteil.

Hier sind einige integrierte Funktionen, mit denen Sie in Python eine Art Typselbstprüfung durchführen können:

id()

Gibt die Identität eines Objekts zurück

dir()

Gibt eine Liste von Namen im aktuellen lokalen Bereich oder eine Liste von Objektattributen zurück

vars()

Gibt das Attribut __dict__ für ein Modul, eine Klasse oder ein Objekt zurück

In den folgenden Abschnitten erfahren Sie, wie diese Funktionen funktionieren und wie Sie sie im Code verwenden können, um eine Typselbstprüfung durchzuführen. Zum Auftakt beginnen Sie mit der Funktion id().

Die Identität eines Objekts kennen: id()

In Python ist jedem einzelnen Objekt eine Identität zugeordnet. Diese Identität ist eine eindeutige und konstante Ganzzahl, die das Objekt während seiner Lebensdauer identifiziert. Zwei Objekte mit nicht überlappender Lebensdauer können dieselbe Identität haben.

Wenn Sie jemals die Identität eines bestimmten Objekts wissen müssen, können Sie die Funktion id() mit dem Objekt als Argument verwenden:

>>> id(42)
4315605776

>>> id("Python")
4315120464

>>> def greet():
...     print("Hello, World!")
...
>>> id(greet)
4307259040

>>> class Demo:
...     pass
...
>>> id(Demo)
4892672720

Wenn Sie id() mit einem beliebigen Python-Objekt als Argument aufrufen, erhalten Sie eine Zahl, die die Identität des Objekts darstellt. In der CPython-Implementierung von Python ist die Identität eines Objekts auch die Speicheradresse, an der sich das Objekt befindet.

Die Kenntnis der Identität eines Objekts kann beim Debuggen Ihres Codes eine große Hilfe sein. Angenommen, Sie möchten Code schreiben, der einzelne Werte aus einer Art Fibonacci-Folge berechnet. Sie können dies auf viele Arten tun. Sie denken jedoch darüber nach, eine Klasse mit aufrufbaren Instanzen und einem Instanzattribut zu verwenden, mit dem Sie bereits berechnete Werte zwischenspeichern können.

Hier ist eine mögliche Implementierung dieser Klasse:

class Fibonaccish:
    def __init__(self, initial_value=1):
        self._cache = [0, initial_value]

    def __call__(self, index):
        if index < len(self._cache):
            fib_number = self._cache[index]
            print(f"{index} {fib_number} id = {id(fib_number)}")
        else:
            fib_number = self(index - 1) + self(index - 2)
            self._cache.append(fib_number)
        return fib_number

In der Initialisierungsmethode von Fibonaccish definieren Sie eine Liste, die den Cache der berechneten Werte enthält. Anschließend definieren Sie die spezielle Methode .__call__(), die es den Instanzen Ihrer Klasse ermöglicht, wie Funktionen aufrufbar zu sein.

Bei dieser Methode ermitteln Sie, ob der Fibonacci-Wert für den Zielindex bereits berechnet und im Cache gespeichert wurde. Anschließend fügen Sie einen Aufruf von print() hinzu, der Ihnen beim Debuggen Ihres Codes mithilfe von id() hilft, um sicherzustellen, dass die zwischengespeicherten Werte verwendet werden.

So funktioniert dieser Kurs in der Praxis:

>>> from fibonacci import Fibonaccish

>>> fibonacci_333 = Fibonacci(333)

>>> fibonacci_333(2)
0 0 id = 94800819952840
1 333 id = 140276932935312
333
>>> fibonacci_333(4)
2 333 id = 140276932934960
1 333 id = 140276932935312
2 333 id = 140276932934960
999

In diesem Codebeispiel erstellen Sie eine Instanz von Fibonaccish mit einem Anfangswert von 333. Die ersten Werte dieser Sequenz sind 0, 333, 333, 666, 999 und 1665.

Die von Ihnen erstellte Instanz ist aufrufbar, sodass Sie sie als reguläre Funktion verwenden können. Anschließend rufen Sie die Instanz mit 2 als Argument auf. Der Aufruf gibt die Identität der Werte 0 und 333 am Index 0 bzw. 1 aus. Als nächstes rufen Sie fibonacci_333() mit 4 als Argument auf. In diesem Fall erhalten Sie die Identität von 333 dreimal, sowohl an Index 1 als auch an Index 2.

Wenn Sie sich die Identitäten ansehen, stellen Sie fest, dass Ihre Funktion dasselbe Objekt für dieselben Indizes verwendet, während es für die beiden verschiedenen Instanzen von 333 unterschiedlich ist. Auf diese Weise können Sie bestätigen, dass die Funktion den Cache wie erwartet verwendet.

Wenn Sie das Beispiel mit der üblichen Fibonacci-Folge Fibonacci(1) wiederholen, werden Sie etwas andere Ergebnisse sehen. In diesem Fall interniert Python 1 unter der Haube, sodass das gleiche Objekt sowohl an Index 1 als auch an Index 2 in Ihrem Cache verwendet wird.

Überprüfen von Namen und Attributen: dir() und vars()

Manchmal müssen Sie die Attribute oder Methoden kennen, die in einem bestimmten Objekt oder Bereich definiert sind. Für diese Art von Anforderung verfügt Python über zwei verschiedene integrierte Funktionen: dir() und vars().

Die Funktion dir() ohne Argumente gibt die Liste der Namen im aktuellen Bereich zurück. Das Ergebnis hängt also von der Stelle ab, an der Sie die Funktion aufrufen. Mit einem beliebigen Python-Objekt als Argument versucht dir(), die Liste der Attribute für dieses Objekt zurückzugeben.

Wenn Sie beispielsweise dir() ohne Argumente in einer neuen REPL-Sitzung aufrufen, erhalten Sie eine Ausgabe wie die folgende:

>>> dir()
[
    '__annotations__',
    '__builtins__',
    '__doc__',
    '__loader__',
    '__name__',
    '__package__',
    '__spec__'
]

Wie Sie sehen können, gibt dir() die Liste der Namen zurück, die in Ihrem aktuellen Bereich definiert sind, der in diesem Beispiel der globale Bereich ist.

Wenn Sie dir() mit einem Python-Objekt als Argument aufrufen, erhalten Sie eine Liste der Attribute und Methoden des Objekts. Wenn das Eingabeobjekt eine Klasse ist, erhalten Sie eine Liste von Methoden und Klassenattributen. Wenn das Objekt eine Instanz einer vorhandenen Klasse ist, erhalten Sie eine Liste mit Methoden, Klassenattributen und Instanzattributen.

Betrachten Sie das folgende Beispiel, das Ihre Klasse Rectangle aus dem Abschnitt über die Funktion super() wiederverwendet:

>>> class Rectangle:
...     def __init__(self, length, width):
...         self.length = length
...         self.width = width
...     def area(self):
...         return self.length * self.width
...     def perimeter(self):
...         return 2 * (self.length + self.width)
...

>>> dir(Rectangle)
[
    '__class__',
    '__delattr__',
    '__dict__',
    ...
    'area',
    'perimeter'
]

>>> rectangle = Rectangle(2, 4)
>>> dir(rectangle)
[
    '__class__',
    '__delattr__',
    '__dict__',
    ...
    'area',
    'length',
    'perimeter',
    'width'
]

Beim ersten Aufruf von dir() erhalten Sie die Klassenattribute und Methoden der Klasse Rectangle. In diesem Fall verwenden Sie das Klassenobjekt als Argument. Im zweiten Aufruf von dir() verwenden Sie eine Instanz von Rectangle als Argument und erhalten alle Methoden, Klassenattribute und Instanzattribute.

Das Standardverhalten von dir() ist für verschiedene Objekttypen unterschiedlich. Hier ist eine Zusammenfassung dieser Unterschiede:

A module object

Gibt die Liste der im Modul definierten Namen zurück.

A type or class object

Gibt die Liste der Namen von Klassenattributen und -methoden sowie der Basisklassen zurück.

Other objects

Gibt die Liste der Attribute und Methoden zurück, einschließlich der Klassenattribute und der Attribute der Basisklassen.

Sie können das Standardverhalten von dir() auch anpassen, indem Sie in Ihren benutzerdefinierten Klassen die spezielle Methode .__dir__() bereitstellen. Dieses Thema geht jedoch über den Rahmen dieses Tutorials hinaus.

Die Funktion vars() gibt das Attribut .__dict__ für ein Modul, eine Klasse, eine Instanz oder ein anderes Objekt mit einem Attribut .__dict__ zurück:

>>> vars(Rectangle)
mappingproxy(
{
    '__module__': '__main__',
    '__init__': <function Rectangle.__init__ at 0x10352d080>,
    'area': <function Rectangle.area at 0x10352d120>,
    'perimeter': <function Rectangle.perimeter at 0x10352d1c0>,
    '__dict__': <attribute '__dict__' of 'Rectangle' objects>,
    '__weakref__': <attribute '__weakref__' of 'Rectangle' objects>,
    '__doc__': None
})

>>> vars(rectangle)
{'length': 2, 'width': 4}

In diesem Beispiel rufen Sie vars() mit der Klasse Rectangle als Argument auf. Sie erhalten das Attribut .__dict__ der Klasse, das Methoden und Klassenattribute enthält. Beachten Sie, dass es auch ein .__dict__-Attribut enthält, das die Attribute der Instanzen der Klasse enthält. Dieses .__dict__ erhalten Sie, wenn Sie vars() mit einer Instanz der Klasse aufrufen.

Das Attribut .__dict__ ist ein Wörterbuch, das als Namespace fungiert, der Namen Objekten zuordnet. Es kann beispielsweise einen Methodennamen einem Methodenobjekt oder einen Attributnamen einem bestimmten Wert oder Objekt zuordnen.

Ausführen von Python-Code aus Strings

In seltenen Situationen kann es nützlich sein, Ausdrücke auszuwerten oder Code auszuführen, der als Zeichenfolgenobjekt vorliegt. Diese Vorgehensweise ist in realem Code nicht üblich, da er möglicherweise nicht sicher ist, insbesondere wenn der Zielcode aus einer nicht vertrauenswürdigen Quelle stammt, z. B. der Eingabe des Benutzers.

Unabhängig von den damit verbundenen Sicherheitsproblemen verfügt Python über drei integrierte Funktionen, mit denen Sie Ausdrücke auswerten oder Code ausführen können, der als Zeichenfolge vorliegt. Hier ist eine Zusammenfassung dieser Funktionen:

eval()

Wertet beliebige Python-Ausdrücke aus einer Zeichenfolge oder einer kompilierten Codeeingabe aus

exec()

Führt beliebigen Python-Code aus einer Zeichenfolge oder einer kompilierten Codeeingabe aus

compile()

Erzeugt ein kompiliertes Codeobjekt aus einer Zeichenfolge

In den folgenden Abschnitten lernen Sie die Grundlagen dieser Funktionen kennen. Zum Auftakt verwenden Sie zunächst die Funktion eval(), um Python-Ausdrücke auszuwerten.

Ausdrücke aus Strings ausführen: eval()

In Python ist ein Ausdruck eine Kombination aus Objekten und Operatoren, die einen Wert zurückgibt. Sie finden verschiedene Arten von Ausdrücken, darunter mathematische, boolesche Ausdrücke, Vergleichsausdrücke, bitweise Ausdrücke und mehr. Wenn Sie mit Ausdrücken arbeiten, können Sie diese als regulären Python-Code ausführen. Was aber, wenn Sie als Zeichenfolgen definierte Ausdrücke auswerten müssen?

Überlegen Sie beispielsweise, wie Sie Folgendes bewerten würden:

"sum([2, 3, 4, 5]) / 4 + 100"

Wenn Sie diese Zeichenfolge als Ausdruck auswerten möchten, müssen Sie die Zeichenfolge analysieren und herausfinden, wie Sie die Operanden und Operatoren extrahieren. Anschließend können Sie den Ausdruck rekonstruieren und im Python-Interpreter ausführen. Dieser Vorgang klingt vielleicht nach einer schnellen Sache. In der Praxis kann dies jedoch überwältigend sein, insbesondere wenn man die unendliche Anzahl verschiedener Ausdrücke bedenkt, die Sie möglicherweise in echtem Code auswerten müssen.

Glücklicherweise verfügt Python über eine integrierte Funktion eval(), mit der Sie Ausdrücke auswerten können, die als Zeichenfolgen vorliegen.

Wenn Sie über eine Zeichenfolge verfügen, die einen gültigen Python-Ausdruck enthält, können Sie eval() mit dieser Zeichenfolge als Argument aufrufen. Die Funktion analysiert die Zeichenfolge, kompiliert sie in Bytecode und wertet sie schließlich als normalen Ausdruck aus:

>>> eval("sum([2, 3, 4, 5]) / 4 + 100")
103.5

Wow! Das ging schnell und reibungslos! Sie haben gerade Ihre Zeichenfolge an eval() übergeben, den Code ausgeführt und das Ergebnis des Ausdrucks erhalten.

Die Signatur von eval() sieht etwa so aus:

eval(expression[, globals[, locals]])

Das erste Argument, expression, enthält den Ausdruck, den Sie auswerten müssen. Die restlichen Argumente sind optional. Deshalb werden sie in eckige Klammern gesetzt. Hier ist eine Zusammenfassung dieser Argumente und ihrer Bedeutung:

expression

Eine Zeichenfolge, die einen gültigen Python-Ausdruck enthält

globals

Ein Wörterbuch, das einen globalen Namespace enthält, der im Aufruf von eval() verwendet werden soll

locals

Ein Wörterbuch, das einen lokalen Namespace enthält, der im Aufruf von eval() verwendet werden soll

Sie haben bereits ein Beispiel für die Verwendung des Arguments expression gesehen, sodass Sie sich jetzt auf die beiden anderen Argumente konzentrieren können. In jedem Beispiel müssen Sie einen Ausdruck angeben.

Hier ist ein Beispiel für die Verwendung des Arguments globals:

>>> numbers = [2, 3, 4, 5]
>>> n = len(numbers)

>>> eval("sum(numbers) / n + 100")
103.5

>>> eval("sum(numbers) / n + 100", {})
Traceback (most recent call last):
    ...
NameError: name 'numbers' is not defined

>>> eval("sum(numbers) / n + 100", {"numbers": numbers, "n": n})
103.5

Standardmäßig hat eval() Zugriff auf den globalen Bereich, sodass Sie alle in diesem Bereich definierten Namen in dem Ausdruck verwenden können, den Sie an die Funktion übergeben. Wenn Sie globals auf ein leeres Wörterbuch festlegen, beschränken Sie den Zugriff auf den globalen Bereich und die Funktion schlägt fehl.

Schließlich können Sie wie im letzten Beispiel ein explizites Wörterbuch verwenden, um die globalen Variablen bereitzustellen, die Sie beim Auswerten des Zielausdrucks verwenden möchten.

Das Argument locals funktioniert ähnlich. Es braucht ein Wörterbuch lokaler Namen:

>>> def evaluator(expression):
...     numbers = [2, 3, 4, 5]
...     n = len(numbers)
...     return eval(expression, {}, {"numbers": numbers, "n": n})
...

>>> evaluator("sum(numbers) / n + 100")
103.5

Innerhalb der Funktion evaluator() definieren Sie Zahlen und n als lokale Variablen. Beim Aufruf von eval() verwenden Sie ein leeres Wörterbuch für globals und ein Wörterbuch, das die lokalen Variablen für locals enthält.

Auch wenn die Funktion eval() wie ein erstaunliches Werkzeug erscheint, müssen Sie bei der Verwendung in Ihrem Code vorsichtig sein. In der Praxis sind Sie sicherer, wenn Sie dieses Tool nicht in realem Code verwenden. Warum?

Die Funktion eval() hat Auswirkungen auf die Sicherheit, die schwer zu umgehen sind. Wenn Sie die Funktion beispielsweise verwenden, um von externen Benutzern bereitgestellte Ausdrücke auszuwerten, setzen Sie Ihr System der Ausführung beliebigen Python-Codes aus.

Weitere Einblicke, wie Sie die mit eval() verbundenen Sicherheitsrisiken reduzieren können, finden Sie im Artikel Minimizing the Security Issues of eval() in the Python eval(): Ausdrücke dynamisch auswerten Tutorial.

Code aus Strings ausführen: exec() und compile()

Die Funktion eval() ist ein leistungsstarkes Werkzeug in Python. Es dient jedoch der Auswertung von Ausdrücken. Manchmal möchten Sie möglicherweise komplexere Codeteile ausführen, die als Zeichenfolgen vorliegen. Beispielsweise möchten Sie möglicherweise Schleifen, bedingte Anweisungen, zusammengesetzte Anweisungen und sogar ganze Skripte ausführen. In diesem Szenario können Sie die integrierten Funktionen exec() und compile() verwenden.

Hier ist die Signatur der Funktion exec():

exec(code [, globals [, locals]])

Das Argument code kann eine Zeichenfolge sein, die gültigen Python-Code enthält. Es kann sich auch um ein kompiliertes Codeobjekt handeln, das Sie mit der Funktion compile() erstellen können. Sie werden gleich mehr über compile() erfahren. Im Moment verwenden Sie eine Zeichenfolge, um das Argument code bereitzustellen.

Wenn code als Zeichenfolge vorliegt, analysiert exec() ihn als Folge von Python-Anweisungen. Anschließend wird der Code in Bytecode kompiliert und schließlich ausgeführt, es sei denn, während des Parsing- oder Kompilierungsschritts tritt ein Syntaxfehler auf.

Betrachten Sie das folgende Beispiel:

>>> functions = [
...     "def add(a, b): return a + b",
...     "def subtract(a, b): return a - b",
...     "def multiply(a, b): return a * b",
...     "def divide(a, b): return a / b",
... ]

>>> for function in functions:
...     exec(function)
...

In diesem Beispiel definieren Sie eine Liste von Zeichenfolgen. Jeder String enthält Python-Funktionen für eine grundlegende arithmetische Operation. Dann starten Sie eine Schleife über die Liste. Mit exec() führen Sie die Strings aus, die die Funktionen definieren. Dieser Schritt bringt jede Funktion in Ihren aktuellen globalen Bereich. Jetzt können Sie sie wie eine reguläre Funktion verwenden:

>>> add(1, 2)
3
>>> subtract(3, 2)
1
>>> multiply(2, 3)
6
>>> divide(6, 3)
2.0

Die arithmetischen Funktionen sind jetzt in Ihrem globalen Bereich verfügbar, sodass Sie sie zum Ausführen Ihrer Berechnungen verwenden können.

Wie eval() akzeptiert exec() die Argumente globals und locals, die wiederum optional sind. Diese Argumente haben in beiden Funktionen ähnliche Bedeutungen, Sie können sie also als Übung ausprobieren.

Wenn Sie eine Zeichenfolge mit Code haben, den Sie mehrmals wiederverwenden möchten, können Sie die Funktion compile() verwenden, um den Code einmal zu kompilieren und ihn überall zu verwenden. Durch diese Vorgehensweise wird Ihr Code effizienter und schneller, da der Kompilierungsschritt nur einmal ausgeführt wird.

Die Signatur von compile() sieht etwa so aus:

compile(source, filename, mode, flags=0, dont_inherit=False, optimize=-1)

Diese Signatur ist etwas kompliziert, da sie mehrere Argumente enthält, die Sie verstehen müssen. Hier ist eine Zusammenfassung der Argumente und ihrer Bedeutung:

source

Enthält den Code, den Sie in Bytecode kompilieren müssen

filename

Halten Sie die Datei bereit, aus der der Code gelesen wurde

mode

Gibt an, welche Art von Code kompiliert werden muss

flags and dont_inherit

Steuert, welche Compileroptionen aktiviert werden sollen und welche zukünftigen Funktionen zugelassen werden sollen

optimize

Gibt den Optimierungsgrad der Kompilierung an

Um aus einem String-Objekt zu lesen, müssen Sie filename auf den Wert "<string>" setzen. Das Argument mode kann einen der folgenden Werte annehmen:

  • "eval", wenn source aus einem einzelnen Ausdruck besteht
  • "exec", wenn source eine Folge von Anweisungen ist
  • "single", wenn source eine einzelne interaktive Anweisung ist

Abhängig vom Quellcode und der Funktion, mit der Sie ihn ausführen möchten, wählen Sie den ersten oder den zweiten Wert aus. Das Argument single ist praktisch, wenn Sie eine Anweisung wie print("Hello, World!") ausführen möchten, die Sie normalerweise in einer interaktiven Sitzung ausführen würden.

Um zu veranschaulichen, wie compile() verwendet wird, betrachten Sie das folgende Spielzeugbeispiel:

>>> code = """
... result = sum(number for number in iterable if not number % 2)
... """

>>> compiled_code = compile(code, "<string>", "exec")

>>> context = {"iterable": [1, 2, 3, 4]}
>>> exec(compiled_code, context)
>>> context["result"]
6

>>> context = {"iterable": [10, 40, 50, 20]}
>>> exec(compiled_code, context)
>>> context["result"]
120

In diesem Beispiel haben Sie einen Codeabschnitt in einer Zeichenfolge. Der Code besteht aus einem Aufruf von sum(), der einen Generatorausdruck umschließt, der eine Iterable von Zahlen annimmt und die geraden Zahlen zurückgibt. Als Nächstes verwenden Sie die Funktion compile(), um die Zeichenfolge in ein Codeobjekt zu kompilieren, das zur Ausführung bereit ist. Das context-Wörterbuch enthält eine Iterable von Zahlen.

Sie rufen exec() mit dem kompilierten Code und dem Kontextwörterbuch als Argumente auf. Beachten Sie, dass Sie context verwenden, um das Argument globals bereitzustellen. Der Aufruf von exec() aktualisiert dieses Wörterbuch mit einem beliebigen Namen, den Sie im kompilierten Code definieren. In diesem speziellen Beispiel enthält context letztendlich die Variable result mit der Summe der geraden Zahlen in der Iterable.

Um auf den berechneten Wert zuzugreifen, verwenden Sie das context-Wörterbuch mit dem Schlüssel "result". Im letzten Beispiel verwenden Sie den kompilierten Code erneut, um eine ähnliche Berechnung mit einer anderen Werteliste durchzuführen.

Verwenden verschiedener Funktionen

Python verfügt über einige weitere integrierte Funktionen, die verschiedene Themen abdecken. Hier ist eine Zusammenfassung dieser Funktionen:

help()

Ruft das integrierte Hilfesystem auf

hash()

Berechnet den Hashwert eines Objekts

__import__()

Wird durch die import-Anweisung aufgerufen

memoryview()

Gibt ein Speicheransichtsobjekt zurück

In den folgenden Abschnitten lernen Sie die Grundlagen dieser Funktionen und wie Sie sie in Ihrem Python-Code oder in einer interaktiven Sitzung der Sprache verwenden. Zum Auftakt beginnen Sie mit der integrierten Funktion help().

Zugriff auf das integrierte Hilfesystem: help()

Die integrierte Funktion help() ist praktisch, wenn Sie in einer Python REPL-Sitzung arbeiten. Mit dieser Funktion erhalten Sie Zugriff auf das eingebaute interaktive Hilfesystem. Fahren Sie fort und öffnen Sie eine interaktive Python-Sitzung in Ihrem Terminal. Rufen Sie dann help() ohne Argumente auf. Ihnen wird das Hilfesystem angezeigt:

>>> help()

Welcome to Python 3.x's help utility!

If this is your first time using Python, you should definitely check out
the tutorial on the internet at https://docs.python.org/3.x/tutorial/.

Enter the name of any module, keyword, or topic to get help on writing
Python programs and using Python modules.  To quit this help utility and
return to the interpreter, just type "quit".

To get a list of available modules, keywords, symbols, or topics, type
"modules", "keywords", "symbols", or "topics".  Each module also comes
with a one-line summary of what it does; to list the modules whose name
or summary contain a given string such as "spam", type "modules spam".

help>

Die Ausgabe heißt Sie herzlich willkommen beim Python-Hilfedienstprogramm. Dann empfiehlt es sich, das offizielle Python-Tutorial zu belegen, wenn Sie mit der Sprache noch nicht vertraut sind. Im dritten und vierten Absatz erhalten Sie Anweisungen zur Verwendung des Hilfesystems.

Am Ende der Seite wartet die Eingabeaufforderung help> auf Ihre Eingabe. Geben Sie den str-Namen ein und drücken Sie dann die Eingabetaste. Sie sehen etwa Folgendes:

Help on class str in module builtins:

class str(object)
 |  str(object='') -> str
 |  str(bytes_or_buffer[, encoding[, errors]]) -> str
 |
 |  Create a new string object from the given object. If encoding or
 |  errors is specified, then the object must expose a data buffer
 |  that will be decoded using the given encoding and error handler.
 |  Otherwise, returns the result of object.__str__() (if defined)
 |  or repr(object).
 |  encoding defaults to sys.getdefaultencoding().
 |  errors defaults to 'strict'.
 |
 |  Methods defined here:
 |
 |  __add__(self, value, /)
 |      Return self+value.
 |
 |  __contains__(self, key, /)
 |      Return key in self.
 ...

Dies ist die Hilfeseite für die Klasse str. Auf dieser Seite finden Sie detaillierte Informationen über den Kurs und seine Ziele. Um die Seite zu verlassen und zum Hilfesystem zurückzukehren, drücken Sie Q.

Im Hilfesystem können Sie die Hilfe für viele Python-Objekte einsehen, darunter integrierte Module, Funktionen, Schlüsselwörter und vieles mehr. Probieren Sie es einfach aus. Vielleicht finden Sie nützliche Informationen!

Es gibt eine zweite Möglichkeit, die Funktion help() zu verwenden. Geben Sie zunächst Q an der help>-Eingabeaufforderung ein und drücken Sie dann die Eingabetaste, um zurückzukehren zu Ihrer interaktiven Sitzung. Sobald Sie dort sind, können Sie help() mit einem beliebigen Python-Objekt als Argument aufrufen. Wenn Sie beispielsweise die Funktion mit der Klasse str als Argument aufrufen, gelangen Sie zur gleichen Seite, die Sie zuvor gesehen haben:

>>> help(str)

Diese Art des Aufrufs von help() ermöglicht Ihnen schnellen Zugriff auf die Hilfeseite eines bestimmten Objekts. Es ist wichtig zu beachten, dass Sie entweder das Objekt direkt als Argument für help() oder den Namen des Objekts als String wie in help("str") verwenden können . In den meisten Fällen ist es jedoch sicherer, den Namen des Objekts als Zeichenfolge zu verwenden:

>>> help(sys)
Traceback (most recent call last):
    ...
NameError: name 'sys' is not defined

In diesem Beispiel versuchen Sie, auf die Hilfeseite für das Modul sys zuzugreifen. Sie verwenden den Namen des Moduls als Argument und erhalten eine NameError-Ausnahme, da das Modul in Ihrem aktuellen Bereich nicht vorhanden ist. Der Aufruf von help() funktioniert sicher, wenn Sie den Namen des Moduls als Zeichenfolge verwenden, wie in "sys". Probieren Sie es einfach aus!

Hash-Codes erstellen: hash()

Wenn Sie in Bereichen wie Datenintegrität, Sicherheit oder Kryptografie arbeiten, sind Sie möglicherweise mit Hash-Codes vertraut. Ein Hash-Code ist eine Zahl, die als digitaler Fingerabdruck für ein bestimmtes Datenelement dienen kann. Es ist normalerweise viel kleiner als die Originaldaten und ermöglicht die Überprüfung der Integrität.

Um einen Hash-Code für ein bestimmtes Objekt zu erstellen, benötigen Sie eine Hash-Funktion. Python verfügt über eine eigene integrierte Funktion zum Erstellen von Hash-Codes. Die Funktion heißt praktischerweise hash().

Die Signatur von hash() sieht wie folgt aus:

hash(object)

Es nimmt ein Objekt als Argument und gibt den Hashwert des Eingabeobjekts zurück. Der Hashwert muss eine Ganzzahl sein.

Hier sind einige Beispiele für die Verwendung der Funktion hash():

>>> hash(42)
42
>>> hash(2.7)
1614090106449586178

>>> hash("Hello")
-6239611042439236057

>>> hash(int)
270201092

>>> class DemoClass: pass
...
>>> hash(DemoClass)
346520709

>>> demo_instance = DemoClass()
>>> hash(demo_instance)
271491289

In diesen Beispielen haben Sie die Funktion hash() mit verschiedenen Objekten verwendet, darunter numerische Werte, Zeichenfolgen, Funktionsobjekte und benutzerdefinierte Klassen. In allen Fällen erhalten Sie einen eindeutigen Hash-Code.

In der Praxis gibt es Objekte, die keinen Hashwert haben:

>>> hash([1, 2, 3])
Traceback (most recent call last):
    ...
TypeError: unhashable type: 'list'

>>> hash({"one": 1, "two": 2})
Traceback (most recent call last):
    ...
TypeError: unhashable type: 'dict'

>>> hash({"red", "green", "bleu"})
Traceback (most recent call last):
    ...
TypeError: unhashable type: 'set'

Sie werden feststellen, dass veränderliche Objekte in Python nicht gehasht werden können, da Sie den Wert eines veränderlichen Objekts während seiner Lebensdauer ändern können.

Objekte aus String-Namen importieren: __import__()

Die in Python integrierte Funktion __import__() ist ein erweitertes Werkzeug, das in der alltäglichen Programmierung nicht üblich ist. Die Funktion wird intern durch die import-Anweisung aufgerufen. Von der direkten Verwendung von __import__() wird zugunsten von importlib.import_module() abgeraten. Da es sich jedoch um eine integrierte Funktion handelt, erfahren Sie in diesem Abschnitt etwas darüber.

Die Signatur von __import__() sieht in etwa wie folgt aus:

__import__(name, globals=None, locals=None, fromlist=(), level=0)

Mit dieser Funktion können Sie ein Modul anhand seines Namens importieren. Dieser name sollte eine Zeichenfolge sein. Hier ist eine Zusammenfassung der Argumente der Funktion und ihrer Bedeutung:

name

Der Name eines Moduls als String

globals

Ein Wörterbuch, das den globalen Namespace darstellt

locals

Ein Wörterbuch, das den lokalen Namespace darstellt

fromlist

Eine Liste von Objekten oder Submodulen, die aus dem Modul importiert werden sollen

level

Ein positiver Wert, der die Anzahl der zu durchsuchenden übergeordneten Verzeichnisse relativ zum Verzeichnis des Moduls angibt, das __import__() aufruft

Um mit der Funktion __import__() etwas zu tun, das import sys entspricht, können Sie etwa Folgendes tun:

>>> sys = __import__("sys")
>>> sys
<module 'sys' (built-in)>

In diesem Beispiel erstellen Sie eine sys-Variable und weisen ihr das Ergebnis des Aufrufs von __import__() mit der Zeichenfolge "sys" als Argument zu. Dieser Aufruf von __import__() importiert das Modul sys in Ihren aktuellen globalen Bereich.

Binärdaten effizient bearbeiten: memoryview()

Mit der integrierten Funktion memoryview() können Sie auf die internen Daten eines Objekts zugreifen, das das Pufferprotokoll unterstützt, z. B. array.array, bytes- und bytearray-Objekte. Mit dieser Funktion können Sie große Datenmengen bearbeiten oder eine Schnittstelle zu Binärdaten herstellen.

Wenn Sie beispielsweise über einen großen Datensatz verfügen und einen Teil davon verwenden möchten, wäre das Erstellen einer Kopie ineffizient. Stattdessen können Sie ein memoryview-Objekt erstellen, um auf die Daten zuzugreifen, ohne sie zu kopieren. Dadurch können Sie weniger Speicher verbrauchen und die Ausführungsgeschwindigkeit erhöhen.

Angenommen, Sie haben die Pixeldaten eines Bildes als bytearray dargestellt und möchten die Pixelwerte invertieren. Um diesen Vorgang effizient durchzuführen, können Sie die Funktion memoryview() verwenden:

>>> image = bytearray([0, 127, 255, 64, 128, 192, 32, 96, 160])
>>> mv = memoryview(image)

>>> for i in range(len(mv)):
...     mv[i] = 255 - mv[i]
...

>>> list(mv)
[255, 128, 0, 191, 127, 63, 223, 159, 95]
>>> list(image)
[255, 128, 0, 191, 127, 63, 223, 159, 95]

In diesem Beispiel erstellen Sie ein memoryview-Objekt, um auf die Daten zuzugreifen, die Ihr Bild darstellen. In der for-Schleife iterieren Sie über die Daten und invertieren die Pixelwerte. Die Transformation spiegelt die Originaldaten wider.

Kurz gesagt, die Funktion memoryview() ist ein leistungsstarkes Tool zum Arbeiten mit Objekten, die das Pufferprotokoll unterstützen, ohne die Daten zu kopieren, wodurch Ihr Code speichereffizienter und schneller wird.

Abschluss

Sie haben die Grundlagen der integrierten Funktionen von Python kennengelernt. Dies sind Funktionen, die Sie direkt verwenden können, ohne etwas zu importieren, da sie im integrierten Bereich oder Namespace verfügbar sind.

Integrierte Funktionen lösen eine Vielzahl gängiger Programmierprobleme wie die Durchführung mathematischer Operationen, die Arbeit mit gängigen Datentypen, die Verarbeitung iterierbarer Daten, die Verarbeitung von Ein- und Ausgaben, die Arbeit mit Bereichen und mehr.

In diesem Tutorial haben Sie Folgendes gelernt:

  • Die Grundlagen der integrierten Funktionen von Python
  • Über häufige Anwendungsfälle der integrierten Funktionen von Python
  • Wie man diese Funktionen verwendet, um praktische Probleme in Python zu lösen

Mit diesem Wissen verfügen Sie über grundlegende Python-Kenntnisse, die Ihnen beim Schreiben von robustem Pythonic-Code helfen. Noch wichtiger ist, dass Sie jetzt alle diese unglaublichen Funktionen kennen und sie in Ihrem Code verwenden können, um häufige Aufgaben effizient zu bewältigen, ohne das Rad neu erfinden zu müssen.