6. Ausdrücke

In diesem Kapitel wird die Bedeutung der Elemente von Ausdrücken in Python erläutert.

Anmerkungen zur Syntax: In diesem und den folgenden Kapiteln wird die Grammatiknotation verwendet, um die Syntax zu beschreiben, nicht die lexikalische Analyse.

Wenn (eine Alternative einer) Syntaxregel folgende Form hat:

name: othername

und es wird keine Semantik angegeben, entspricht die Semantik dieser Form von name der von othername .

6.1. Arithmetische Umrechnungen

Wenn in einer der folgenden Beschreibungen eines arithmetischen Operators der Ausdruck „die numerischen Argumente werden in einen gemeinsamen Real-Typ konvertiert“ verwendet wird, bedeutet dies, dass die Implementierung des Operators für integrierte numerische Typen so funktioniert, wie im Abschnitt Numerische Typen der Dokumentation zur Standardbibliothek beschrieben.

Für bestimmte Operatoren und nicht-numerische Operanden gelten einige zusätzliche Regeln (beispielsweise bei einer Zeichenkette als linkes Argument des Operators %). Erweiterungen müssen ihr eigenes Konvertierungsverhalten definieren.

6.2. Atoms

Atoms sind die elementarsten Bestandteile von Ausdrücken. Die einfachsten Atoms sind integrierte Konstanten, Namen und Literale. Komplexere Atoms stehen zwischen paarigen Begrenzern:

Formal lautet die Syntax für Atoms wie folgt:

atom:
   | builtin_constant
   | identifier
   | literal
   | parenthesized_enclosure
   | bracketed_enclosure
   | braced_enclosure
parenthesized_enclosure:
   | group
   | tuple
   | yield_atom
   | generator_expression
bracketed_enclosure:
   | listcomp
   | list
braced_enclosure:
   | dictcomp
   | dict
   | setcomp
   | set

6.2.1. Integrierte Konstanten

Die Schlüsselwörter True, False und None bezeichnen integrierte Konstanten. Das Token ... bezeichnet die Konstante Ellipsis.

Die Auswertung dieser Atoms liefert den entsprechenden Wert.

Bemerkung

Es stehen noch einige weitere integrierte Konstanten als globale Variablen zur Verfügung, aber nur die hier genannten sind Schlüsselwörter. Insbesondere dürfen diese Namen nicht neu zugewiesen oder als Attribute verwendet werden:

>>> False = 123
  File "<input>", line 1
   False = 123
   ^^^^^
SyntaxError: cannot assign to False

Formal lautet die Syntax für integrierte Konstanten wie folgt:

builtin_constant: 'True' | 'False' | 'None' | '...'

6.2.2. Bezeichner (Namen)

Ein Bezeichner, der als Atom auftritt, ist ein Name. Die lexikalische Definition findest du im Abschnitt Names (identifiers and keywords) , die Dokumentation zu Benennung und Bindung im Abschnitt Benennung und Zuordnung .

Wenn der Name an ein Objekt gebunden ist, liefert die Auswertung des Atoms dieses Objekt. Ist ein Name nicht gebunden, löst der Versuch, ihn auszuwerten, eine NameError-Ausnahme aus.

6.2.2.1. Private Namensumformung

Wenn ein Bezeichner, der wörtlich in einer Klassendefinition vorkommt, mit zwei oder mehr Unterstrichen beginnt und nicht mit zwei oder mehr Unterstrichen endet, gilt er als privater Name dieser Klasse.

Siehe auch

Die Klassenspezifikationen.

Genauer gesagt werden private Namen in eine längere Form umgewandelt, bevor Code für sie generiert wird. Ist der umgewandelte Name länger als 255 Zeichen, kann es zu einer implementierungsabhängigen Kürzung kommen.

Die Umformung ist unabhängig vom syntaktischen Kontext, in dem der Bezeichner verwendet wird, jedoch werden nur die folgenden privaten Bezeichner umgestaltet:

  • Jeder Name, der als Name einer Variablen verwendet wird, die zugewiesen oder ausgelesen wird, sowie jeder Name eines Attributs, auf das zugegriffen wird.

    Das Attribut __name__ von verschachtelten Funktionen, Klassen und Typaliasen wird jedoch nicht umbenannt.

  • Der Name importierter Module, z. B. __spam in import __spam . Wenn das Modul Teil eines Pakets ist (d. h., sein Name enthält einen Punkt), wird der Name nicht umgewandelt, z. B. wird __foo in import __foo.bar nicht umgewandelt.

  • Der Name eines importierten Mitglieds, z. B. __f in from spam import __f .

Die Transformationsregel ist wie folgt definiert:

  • Der Klassenname, bei dem führende Unterstriche entfernt und ein einzelner führender Unterstrich eingefügt wurde, wird vor den Bezeichner gesetzt. So wird beispielsweise der Bezeichner __spam , der in einer Klasse namens Foo , _Foo oder __Foo vorkommt, in _Foo__spam umgewandelt.

  • Wenn der Klassenname ausschließlich aus Unterstrichen besteht, erfolgt keine Umwandlung. Der Bezeichner __spam , der beispielsweise in einer Klasse namens _ oder __ vorkommt, bleibt unverändert.

6.2.3. Literale

Ein Literal ist eine textuelle Darstellung eines Werts. Python unterstützt numerische Literale, Zeichenkettenliterale und Byte-Literale. Formatzeichenfolgen und Vorlagenzeichenfolgen werden als Zeichenkettenliterale behandelt.

Numerische Literale bestehen aus einem einzelnen NUMBER-Token, das eine Ganzzahl, eine Gleitkommazahl oder eine imaginäre Zahl bezeichnet. Weitere Informationen findest du im Abschnitt Numeric literals in der Dokumentation zur lexikalischen Analyse.

Zeichenfolgen- und Byte-Literale können aus mehreren Tokens bestehen. Weitere Informationen findest du im Abschnitt Verkettung von Zeichenfolgenliteralen .

Beachte, dass negative und komplexe Zahlen, wie beispielsweise -3 oder 3+4.2j, syntaktisch gesehen keine Literale sind, sondern unäre oder binäre arithmetische Operationen, an denen der Operator - oder + beteiligt ist.

Die Auswertung eines Literals ergibt ein Objekt des angegebenen Typs (int, float, complex, str, bytes oder Template) mit dem angegebenen Wert. Bei Gleitkomma- und imaginären Literalen kann der Wert approximiert werden.

Die formale Grammatik für Literale lautet:

literal: strings | NUMBER

6.2.3.1. Literale und Objektidentität

Alle Literale entsprechen unveränderlichen Datentypen, weshalb die Identität des Objekts weniger wichtig ist als sein Wert. Bei mehrfacher Auswertung von Literalen mit demselben Wert (entweder an derselben Stelle im Programmtext oder an einer anderen Stelle) kann entweder dasselbe Objekt oder ein anderes Objekt mit demselben Wert resultieren.

Details zur CPython-Implementierung

In CPython beispielsweise werden kleine Ganzzahlen mit demselben Wert zu demselben Objekt ausgewertet:

>>> x = 7
>>> y = 7
>>> x is y
True

Große Ganzzahlen werden jedoch zu unterschiedlichen Objekten ausgewertet:

>>> x = 123456789
>>> y = 123456789
>>> x is y
False

Dieses Verhalten kann sich in zukünftigen Versionen von CPython ändern. Insbesondere hat sich die Grenze zwischen „kleinen“ und „großen“ Ganzzahlen in der Vergangenheit bereits geändert.

SyntaxWarning CPython gibt bei einem Vergleich von Literalen mit is die Fehlermeldung „:py“ aus

>>> x = 7
>>> x is 7
<input>:1: SyntaxWarning: "is" with 'int' literal. Did you mean "=="?
True

Weitere Informationen findest du unter Wann kann ich mich auf Identitätstests mit dem Operator is verlassen?.

Vorlagenzeichenfolgen sind unveränderlich, können jedoch auf veränderbare Objekte als Interpolation-Werte verweisen. Im Sinne dieses Abschnitts haben zwei t-Strings den „gleichen Wert“, wenn sowohl ihre Struktur als auch die Identität der Werte übereinstimmen.

Derzeit führt jede Auswertung einer Vorlagenzeichenfolge zu einem anderen Objekt.

6.2.3.2. Verkettung von Zeichenfolgenliteralen

Es sind mehrere aufeinanderfolgende Zeichenfolgen- oder Byte-Literale zulässig, die möglicherweise unterschiedliche Anführungszeichenkonventionen verwenden, und ihre Bedeutung entspricht ihrer Verkettung:

>>> "hello" 'world'
"helloworld"

Diese Funktion ist auf syntaktischer Ebene definiert und funktioniert daher nur mit Literalen. Um Zeichenfolgenausdrücke zur Laufzeit zu verketten, kann der Operator „+“ verwendet werden:

>>> greeting = "Hello"
>>> space = " "
>>> name = "Blaise"
>>> print(greeting + space + name)   # nicht: print(greeting space name)
Hello Blaise

Bei der literalen Verkettung können einfache Zeichenfolgen, Zeichenfolgen in dreifachen Anführungszeichen und formatierte Zeichenfolgenliterale beliebig miteinander kombiniert werden. Zum Beispiel:

>>> "Hello" r', ' f"{name}!"
"Hello, Blaise!"

Diese Funktion kann genutzt werden, um die Anzahl der benötigten Backslashes zu reduzieren, lange Zeichenfolgen bequem auf mehrere Zeilen aufzuteilen oder sogar Kommentare zu Teilen der Zeichenfolgen hinzuzufügen. Zum Beispiel:

re.compile("[A-Za-z_]"       # Buchstabe oder Unterstrich
           "[A-Za-z0-9_]*"   # Buchstabe, Ziffer oder Unterstrich
          )

Byte-Literale dürfen jedoch nur mit anderen Byte-Literalen kombiniert werden, nicht mit Zeichenfolgenliteralen jeglicher Art. Außerdem dürfen Template-Zeichenfolgenliterale nur mit anderen Template-Zeichenfolgenliteralen kombiniert werden:

>>> t"Hello" t"{name}!"
Template(strings=('Hello', '!'), interpolations=(...))

Formal:

strings: (STRING | fstring)+ | tstring+

6.2.4. Geklammerte Gruppen

Eine geklammerte Gruppe ist ein Ausdruck, der in runde Klammern eingeschlossen ist. Die Gruppe wird zum selben Wert ausgewertet wie der Ausdruck darin.

Gruppen dienen dazu, die Reihenfolge der Rechenoperatoren aufzuheben oder zu verdeutlichen, genau wie in der mathematischen Schreibweise. Zum Beispiel:

>>> 3 << 2 | 4
12
>>> 3 << (2 | 4)   # Vorrang des | (bitweises ODER) aufheben
192
>>> (3 << 2) | 4   # wie ohne Klammern (aber deutlicher)
12

Beachte, dass nicht alles in Klammern eine Gruppe ist. Eine geklammerte Gruppe muss genau einen Ausdruck enthalten und darf nicht mit einem Komma enden. Weitere geklammerte Formen findest du unter Tupel-Displays und Generatorausdrücke.

Formal lautet die Syntax für Gruppen wie folgt:

group: '(' assignment_expression ')'

6.2.5. Container-Displays

Zum Erzeugen integrierter Container (Listen, Mengen, Tupel oder Wörterbücher) stellt Python eine besondere Schreibweise bereit, die Displays heißt. Zwischen den vier Arten von Displays gibt es feine Unterschiede, die in den folgenden Abschnitten beschrieben werden. Alle Displays bestehen jedoch aus kommagetrennten Elementen, die zwischen paarigen Begrenzern stehen.

Ein Listen-Display ist zum Beispiel eine Folge von Ausdrücken in eckigen Klammern:

>>> ["one", "two", "three"]
['one', 'two', 'three']
>>> [1 + 2, 2 + 3]
[3, 5]

Bei Listen-, Tupel- und Wörterbuch-Displays (nicht aber bei Mengen-Displays) darf die Folge leer sein:

>>> []  # leere Liste
[]
>>> ()  # leeres Tupel
()
>>> {}  # leeres Wörterbuch
{}

Ist die Folge nicht leer, darf auf die Elemente ein zusätzliches Komma folgen, das keine Wirkung hat:

>>> ["one", "two", "three",]  # beachte das Komma nach "three"
['one', 'two', 'three']

Bemerkung

Das abschließende Komma wird oft bei Displays verwendet, die sich über mehrere Zeilen erstrecken (mittels impliziter Zeilenverbindung). Wer später einen neuen Eintrag am Ende ergänzt, muss dann keine bestehende Zeile ändern:

>>> [
...     'one',
...     'two',
...     'three',
... ]
['one', 'two', 'three']

Zur Laufzeit werden bei der Auswertung eines Displays die aufgeführten Elemente von links nach rechts ausgewertet und in einen neuen Container des passenden Typs eingefügt.

Bei Tupel-, Listen- und Mengen-Displays (nicht aber bei Wörterbuch-Displays) darf jedem Element ein Sternchen (*) vorangestellt werden. Das bezeichnet das Entpacken von Iterables. Zur Laufzeit muss der mit Sternchen versehene Ausdruck zu einem Iterable ausgewertet werden, dessen Inhalt an der Stelle des Entpackens in den Container eingefügt wird. Zum Beispiel:

>>> numbers = (1, 2)
>>> [*numbers, 'word', *numbers]
[1, 2, 'word', 1, 2]

Wörterbuch-Displays nutzen einen ähnlichen Mechanismus namens Wörterbuch-Entpacken, der mit einem doppelten Sternchen (**) geschrieben wird. Einzelheiten findest du unter Wörterbuch-Displays.

Eine weiterführende Form von Displays sind Comprehensions, bei denen die Elemente über Schleifen- und Filteranweisungen berechnet werden. Einzelheiten findest du im Abschnitt Comprehensions.

Added in version 3.5: Das Entpacken von Iterables und Wörterbüchern in Displays, ursprünglich vorgeschlagen von PEP 448.

6.2.5.1. Listen-Displays

Ein Listen-Display ist eine möglicherweise leere Folge von Ausdrücken in eckigen Klammern. Zum Beispiel:

>>> ["one", "two", "three"]
['one', 'two', 'three']
>>> ["one"]  # einelementige Liste
['one']
>>> []       # leere Liste
[]

Allgemeine Hinweise zu Displays findest du unter Container-Displays.

Die formale Grammatik für Listen-Displays lautet:

list: '[' [flexible_expression_list] ']'

6.2.5.2. Mengen-Displays

Ein Mengen-Display ist eine nicht leere Folge von Ausdrücken in geschweiften Klammern. Zum Beispiel:

>>> {"one", "two", "three"}
{'one', 'three', 'two'}
>>> {"one"}  # einelementige Menge
{'one'}

Allgemeine Hinweise zu Displays findest du unter Container-Displays.

Für die leere Menge gibt es keine eigene Schreibweise. Das Literal {} ist ein Wörterbuch-Display, das ein leeres Wörterbuch erzeugt. Rufe set() ohne Argumente auf, um eine leere Menge zu erhalten.

Die formale Grammatik für Mengen-Displays lautet:

set: '{' flexible_expression_list '}'

6.2.5.3. Tupel-Displays

Ein Tupel-Display ist eine Folge von Ausdrücken in runden Klammern. Zum Beispiel:

>>> (1, 2)
(1, 2)
>>> ()  # ein leeres Tupel
()

Allgemeine Hinweise zu Displays findest du unter Container-Displays.

Um Mehrdeutigkeiten zu vermeiden, braucht ein Tupel-Display mit genau einem Element ein abschließendes Komma. Ohne dieses erhältst du eine geklammerte Gruppe:

>>> ('single',)  # einelementiges Tupel
('single',)
>>> ('single')   # kein Komma: eine einzelne Zeichenkette
'single'

Anders gesagt ist ein Tupel-Display eine geklammerte Liste aus entweder:

  • zwei oder mehr kommagetrennten Ausdrücken oder

  • null oder mehr Ausdrücken, auf die jeweils ein Komma folgt.

Da Tupel unveränderlich sind, gelten die Regeln zur Objektidentität von Literalen auch für Tupel: Zur Laufzeit können zwei Vorkommen von Tupeln mit denselben Werten dasselbe Objekt ergeben, müssen es aber nicht.

Bemerkung

Die Syntax von Python kennt außerdem Ausdruckslisten, bei denen eine kommagetrennte Liste von Ausdrücken nicht in Klammern steht, aber zu einem Tupel ausgewertet wird.

Anders gesagt ist bei der Tupel-Syntax das Komma wichtiger als die Klammern. Nur das leere Tupel wird ohne Komma geschrieben.

Die formale Grammatik für Tupel-Displays lautet:

tuple:
   | '(' flexible_expression (',' flexible_expression)+ [','] ')'
   | '(' flexible_expression ',' ')'
   | '(' ')'

6.2.5.4. Wörterbuch-Displays

Ein Wörterbuch-Display ist eine möglicherweise leere Folge von Wörterbucheinträgen in geschweiften Klammern. Jeder Wörterbucheintrag ist ein durch Doppelpunkt getrenntes Ausdruckspaar: der Schlüssel und der zugehörige Wert. Zum Beispiel:

>>> {1: 'one', 2: 'two'}
{1: 'one', 2: 'two'}

Zur Laufzeit werden bei der Auswertung einer Dictionary Comprehension die Ausdrücke von links nach rechts ausgewertet. Jedes Schlüsselobjekt dient als Schlüssel im Wörterbuch, unter dem der zugehörige Wert abgelegt wird. Damit lässt sich derselbe Schlüssel in der Comprehension mehrfach angeben. Der Wert im fertigen Wörterbuch ist dann der zuletzt angegebene. Zum Beispiel:

>>> {
...     1: 'this will be overridden',
...     2: 'two',
...     1: 'also overridden',
...     1: 'one',
... }
{1: 'one', 2: 'two'}

Statt eines Schlüssel-Wert-Paares kann ein Wörterbucheintrag auch ein Ausdruck sein, dem ein doppeltes Sternchen ** vorangestellt ist. Das bezeichnet das Wörterbuch-Entpacken. Zur Laufzeit muss der Ausdruck zu einem mapping ausgewertet werden. Jeder Eintrag dieser Zuordnung wird dem neuen Wörterbuch hinzugefügt. Wie bei Schlüssel-Wert-Paaren ersetzen spätere Werte die Werte, die frühere Einträge und Entpackungen bereits gesetzt haben. So lässt sich eine Reihe von Vorgabewerten überschreiben:

>>> defaults = {'color': 'blue', 'count': 8}
>>> overrides = {'color': 'yellow'}
>>> {**defaults, **overrides}
{'color': 'yellow', 'count': 8}

Added in version 3.5: Das Entpacken in Wörterbuch-Displays, ursprünglich vorgeschlagen von PEP 448.

Die formale Grammatik für Wörterbuch-Displays lautet:

dict:                   '{' [double_starred_kvpairs] '}'
double_starred_kvpairs: ','.double_starred_kvpair+ [',']
double_starred_kvpair:  '**' or_expr | kvpair
kvpair:                 expression ':' expression

6.2.6. Comprehensions

Listen-, Mengen- und Wörterbuch-Comprehensions sind eine Form von Container-Displays, bei der die Elemente über Schleifen- und Filteranweisungen berechnet statt einzeln aufgeführt werden.

In ihrer einfachsten Form besteht eine Comprehension aus einem einzelnen Ausdruck, auf den eine for-Klausel folgt. Die for-Klausel hat dieselbe Syntax wie der Kopf einer for-Anweisung, allerdings ohne abschließenden Doppelpunkt.

Eine Liste der ersten zehn Quadratzahlen sieht zum Beispiel so aus:

>>> [x**2 for x in range(10)]
[0, 1, 4, 9, 16, 25, 36, 49, 64, 81]

Zur Laufzeit erzeugt eine Listen-Comprehension eine neue Liste. Der Ausdruck nach in muss zu einem iterable ausgewertet werden. Für jedes Element dieses Iterables wird das Element wie in einer for-Anweisung an das Ziel der for-Klausel gebunden. Anschließend wird der Ausdruck vor for mit dem Ziel im Gültigkeitsbereich ausgewertet und das Ergebnis der neuen Liste hinzugefügt. Das obige Beispiel entspricht damit ungefähr der Definition und dem Aufruf der folgenden Funktion:

def make_list_of_squares(iterable):
    result = []
    for x in iterable:
        result.append(x**2)
    return result

make_list_of_squares(range(10))

Mengen-Comprehensions funktionieren ähnlich. Hier zum Beispiel eine Menge von Kleinbuchstaben:

>>> {x.lower() for x in ['a', 'A', 'b', 'C']}
{'c', 'a', 'b'}

Zur Laufzeit entspricht das ungefähr dem Aufruf dieser Funktion:

def make_lowercase_set(iterable):
    result = set(iterable)
    for x in iterable:
        result.append(x.lower())
    return result

make_lowercase_set(['a', 'A', 'b', 'C'])

Dictionary Comprehensions beginnen statt mit einem Ausdruck mit einem durch Doppelpunkt getrennten Schlüssel-Wert-Paar. Zum Beispiel:

>>> {func.__name__: func for func in [print, hex, any]}
{'print': <built-in function print>,
 'hex': <built-in function hex>,
 'any': <built-in function any>}

Zur Laufzeit entspricht das ungefähr Folgendem:

def make_dict_mapping_names_to_functions(iterable):
    result = {}
    for func in iterable:
        result[func.__name__] = func
    return result

iterable([print, hex, any])

Wie bei den anderen Arten von Wörterbuch-Displays darf derselbe Schlüssel mehrfach angegeben werden. Frühere Werte werden von später ausgewerteten überschrieben.

Tupel-Comprehensions gibt es nicht. Die entsprechende Schreibweise ist stattdessen den Generatorausdrücken vorbehalten, aus denen sich ein Tupel so erzeugen lässt:

>>> tuple(x**2 for x in range(10))
(0, 1, 4, 9, 16, 25, 36, 49, 64, 81)

Geändert in Version 3.8: Vor Python 3.8 war die Auswertungsreihenfolge von Schlüssel und Wert in Dict-Comprehensions nicht eindeutig definiert. In CPython wurde der Wert vor dem Schlüssel ausgewertet. Ab Version 3.8 wird der Schlüssel vor dem Wert ausgewertet, wie unter PEP 572 vorgeschlagen.

6.2.6.1. Filtern in Comprehensions

Auf die for-Klausel darf eine if-Klausel mit einem Ausdruck folgen.

Eine Liste der Namen aus dem Modul math, die mit f beginnen, sieht zum Beispiel so aus:

>>> [name for name in vars(math) if name.startswith('f')]
['fabs', 'factorial', 'floor', 'fma', 'fmod', 'frexp', 'fsum']

Zur Laufzeit wird der Ausdruck nach if ausgewertet, bevor ein Element in den entstehenden Container aufgenommen wird. Ist er falsch, wird das Element übersprungen. Das obige Beispiel entspricht damit ungefähr der Definition und dem Aufruf der folgenden Funktion:

def get_math_f_names(iterable):
    result = []
    for name in iterable:
        if name.startswith('f'):
           result.append(name)
    return result

get_math_f_names(vars(math))

Das Filtern ist ein Sonderfall komplexerer Comprehensions. Eine formalere Beschreibung findest du im nächsten Abschnitt.

6.2.6.2. Komplexe Comprehensions

Allgemein darf auf die erste for-Klausel einer Comprehension eine beliebige Zahl weiterer for- oder if-Klauseln folgen. Hier zum Beispiel eine Liste der Namen, die zwei Python-Module bereitstellen, gefiltert auf diejenigen, die mit a beginnen:

>>> import array
>>> import math
>>> [
...     name
...     for module in [array, math]
...     for name in vars(module)
...     if name.startswith('a')
... ]
['array', 'acos', 'acosh', 'asin', 'asinh', 'atan', 'atan2', 'atanh']

Zur Laufzeit entspricht das ungefähr der Definition und dem Aufruf von:

def get_a_names(iterable):
    result = []
    for module in iterable:
        for name in vars(module):
            if name.startswith('a'):
                result.append(name)
    return result

get_a_names([array, math])

Die Elemente des neuen Containers sind diejenigen, die entstehen, wenn man jede for- oder if-Klausel als Block auffasst, diese von links nach rechts ineinander schachtelt und jedes Mal, wenn der innerste Block erreicht wird, den Ausdruck auswertet, um ein Element (oder einen Wörterbucheintrag) zu erzeugen.

Abgesehen vom Iterable-Ausdruck in der äußersten linken for-Klausel wird die Comprehension in einem eigenen, implizit verschachtelten Gültigkeitsbereich ausgeführt. So ist sichergestellt, dass Namen, denen in der Zielliste etwas zugewiesen wird, nicht in den umgebenden Gültigkeitsbereich „durchsickern“. Zum Beispiel:

>>> x = 'old value'
>>> [x**2 for x in range(10)]  # dieses `x` ist lokal zur Comprehension
>>> x
'old value'

Der Iterable-Ausdruck in der äußersten linken for-Klausel wird unmittelbar im umgebenden Gültigkeitsbereich ausgewertet und dann als Argument an den implizit verschachtelten Gültigkeitsbereich übergeben.

Nachfolgende for-Klauseln sowie eine etwaige Filterbedingung in der äußersten linken for-Klausel lassen sich nicht im umgebenden Gültigkeitsbereich auswerten, da sie von den Werten abhängen können, die das äußerste linke Iterable liefert.

Um sicherzustellen, dass das Ergebnis der Auswertung stets ein Container des entsprechenden Typs ist, sind Ausdrücke wie yield und yield from im implizit verschachtelten Gültigkeitsbereich nicht zulässig.

Zuweisungsausdrücke sind weder innerhalb der Iterable-Ausdrücke einer Comprehension erlaubt (also der Ausdrücke nach dem Schlüsselwort in) noch irgendwo innerhalb von Comprehensions, die unmittelbar in einer Klassendefinition stehen.

Geändert in Version 3.8: yield und yield from ist im implizit verschachtelten Gültigkeitsbereich verboten.

6.2.6.3. Entpacken in Comprehensions

Ist der Ausdruck einer Listen- oder Mengen-Comprehension mit einem Sternchen versehen, wird das Ergebnis entpackt und liefert null oder mehr Elemente.

Das wird oft zum „Verflachen“ von Listen genutzt, zum Beispiel:

>>> students = ['Petr', 'Blaise', 'Jarka']
>>> teachers = ['Salim', 'Bartosz']
>>> lists_of_people = [students, teachers]
>>> [*people for people in lists_of_people]
['Petr', 'Blaise', 'Jarka', 'Salim', 'Bartosz']

Zur Laufzeit entspricht diese Comprehension ungefähr Folgendem:

def flatten_names(lists_of_people):
    result = []
    for people in lists_of_people:
        result.extend(people)
    return result

In Dictionary Comprehensions wird ein Ausdruck mit doppeltem Sternchen ausgewertet und anschließend per Wörterbuch-Entpacken aufgelöst, wodurch null oder mehr Schlüssel-Wert-Paare in das neue Wörterbuch eingefügt werden. Wie bei den anderen Arten von Wörterbuch-Displays gilt: Wird derselbe Schlüssel mehrfach angegeben, steht im Ergebnis der zuletzt angegebene Wert.

Zum Beispiel:

>>> system_defaults = {'color': 'blue', 'count': 8}
>>> user_defaults = {'color': 'yellow'}
>>> overrides = {'count': 5}

>>> configuration_sets = [system_defaults, user_defaults, overrides]

>>> {**d for d in configuration_sets}
{'color': 'yellow', 'count': 5}

Added in version 3.15: Das Entpacken in Comprehensions mit den Operatoren * und ** wurde mit PEP 798 eingeführt.

6.2.6.4. Asynchrone Comprehensions

In einer async def-Funktion darf eine async for-Klausel verwendet werden, um über einen asynchronous iterator zu iterieren. Eine Comprehension in einer async def-Funktion kann hinter dem einleitenden Ausdruck entweder eine for- oder eine async for-Klausel enthalten, darf weitere for- oder async for-Klauseln besitzen und auch await-Ausdrücke verwenden.

Enthält eine Comprehension async for-Klauseln, oder enthält sie await-Ausdrücke beziehungsweise weitere asynchrone Comprehensions an einer anderen Stelle als dem Iterable-Ausdruck der äußersten linken for-Klausel, so heißt sie asynchrone Comprehension. Eine asynchrone Comprehension kann die Ausführung der Coroutine-Funktion, in der sie steht, anhalten.

Added in version 3.6: Asynchrone Comprehensions wurden mit PEP 530 eingeführt.

Geändert in Version 3.11: Asynchrone Comprehensions sind nun innerhalb von Comprehensions in asynchronen Funktionen zulässig. Äußere Comprehensions werden implizit asynchron.

6.2.6.5. Formale Grammatik für Comprehensions

Die formale Grammatik für Comprehensions lautet:

listcomp:      '[' comprehension ']'
setcomp:       '{' comprehension '}'
comprehension: flexible_expression for_if_clause+

dictcomp:
    | '{' kvpair for_if_clause+ '}'
    | '{' '**' expression for_if_clause+ '}'

for_if_clause:
    | ['async'] 'for' target_list 'in' or_test ('if' or_test)*

6.2.7. Generatorausdrücke

Die Syntax für Generatorausdrücke entspricht der für Listen-Comprehensions, mit dem Unterschied, dass sie in runde Klammern statt in eckige Klammern gesetzt werden. Zum Beispiel:

>>> iterator = (x ** 2 for x in range(10))
>>> iterator
<generator object <genexpr> at ...>

Zur Laufzeit wird ein Generatorausdruck zu einem Generator-Iterator ausgewertet, der dieselben Werte liefert wie die entsprechende Listenkomprimierung:

>>> list(iterator)
[0, 1, 4, 9, 16, 25, 36, 49, 64, 81]

Das obige Beispiel entspricht also in etwa der Definition und dem Aufruf der folgenden Generatorfunktion:

def make_generator_of_squares(iterator):
    for x in iterator:
        yield x ** 2

make_generator_of_squares(iter(range(10)))

Die umschließenden Klammern können bei Aufrufen weggelassen werden, wenn der Generatorausdruck das einzige Positionsargument ist und keine Schlüsselwortargumente vorhanden sind. Weitere Informationen findest du im Abschnitt Aufrufe. Beispiel:

# Die Klammern nach `sum` sind Teil der Aufrufsyntax:
>>> sum(x ** 2 for x in range(10))
285

# Der Generator benötigt eigene Klammern, wenn er nicht das einzige Argument ist:
>>> sum((x ** 2 for x in range(10)), start=1000)
1285

Der iterierbare Ausdruck in der ganz links stehenden for-Klausel wird sofort ausgewertet, sodass ein durch diesen Ausdruck ausgelöster Fehler an der Stelle ausgegeben wird, an der der Generatorausdruck definiert ist, und nicht an der Stelle, an der der erste Wert abgerufen wird:

>>> (x ** 2 for x in nonexistent_iterable)
Traceback (most recent call last):
  ...
NameError: name 'nonexistent_iterable' is not defined

Nachdem der Ausdruck ausgewertet wurde, wird aus dem Ergebnis ein Iterator erstellt, als ob die Funktion iter() darauf aufgerufen worden wäre. Jeder Fehler, der beim Erstellen des Iterators auftritt, wird ebenfalls sofort ausgegeben:

>>> (x ** 2 for x in None)
Traceback (most recent call last):
  ...
TypeError: 'NoneType' object is not iterable

Alle anderen Ausdrücke werden verzögert ausgewertet, genau wie bei normalen Generatoren (d. h., wenn der Iterator aufgefordert wird, einen Wert auszugeben):

>>> iterator = (nonexistent_value for x in range(10))
>>> iterator
<generator object <genexpr> at ...>
>>> list(iterator)
Traceback (most recent call last):
  ...
NameError: name 'nonexistent_value' is not defined
>>> iterator = (x * y for x in range(10) for y in nonexistent_iterable)
>>> iterator
<generator object <genexpr> at ...>
>>> list(iterator)
Traceback (most recent call last):
  ...
NameError: name 'nonexistent_iterable' is not defined

Um eine Beeinträchtigung der erwarteten Funktionsweise des Generatorausdrucks selbst zu vermeiden, sind Ausdrücke vom Typ yield und yield from innerhalb des implizit verschachtelten Gültigkeitsbereichs nicht zulässig.

Wenn ein Generatorausdruck entweder async for-Klauseln oder await-Ausdrücke enthält, wird er als asynchroner Generatorausdruck bezeichnet. Ein asynchroner Generatorausdruck gibt ein neues asynchrones Generatorobjekt zurück, bei dem es sich um einen asynchronen Iterator handelt (siehe Asynchrone Iteratoren).

Die formale Grammatik für Generatorausdrücke lautet:

generator_expression: "(" comprehension ")"

Added in version 3.6: Es wurden asynchrone Generatorausdrücke eingeführt.

Geändert in Version 3.7: Vor Python 3.7 konnten asynchrone Generatorausdrücke nur in async def-Koroutinen verwendet werden. Ab Version 3.7 können asynchrone Generatorausdrücke in jeder Funktion verwendet werden.

Geändert in Version 3.8: yield und yield from ist im implizit verschachtelten Gültigkeitsbereich verboten.

6.2.8. Yield Ausdrücke

yield_atom:       "(" yield_expression ")"
yield_from:       "yield" "from" expression
yield_expression: "yield" yield_list | yield_from

Der yield-Ausdruck wird bei der Definition einer Generator-Funktion oder einer asynchronen Generator-Funktion verwendet und kann daher nur im Körper einer Funktionsdefinition verwendet werden. Die Verwendung einer yield-Anweisung im Funktionskörper führt dazu, dass diese Funktion zu einer Generatorfunktion wird, und die Verwendung in einem async def-Funktionskörper führt dazu, dass diese Coroutine-Funktion zu einer asynchronen Generatorfunktion wird. Zum Beispiel:

def gen():  # definiert eine Generatorfunktion
    yield 123

async def agen(): # definiert eine asynchrone Generatorfunktion
    yield 123

Aufgrund ihrer Auswirkungen auf den übergeordneten Gültigkeitsbereich sind yield-Ausdrücke nicht als Teil der implizit definierten Gültigkeitsbereiche zulässig, die zur Implementierung von Comprehensions und Generatorausdrücken verwendet werden.

Geändert in Version 3.8: Yield-Ausdrücke sind in den implizit verschachtelten Gültigkeitsbereichen verboten, die zur Implementierung von Comprehensions und Generatorausdrücken verwendet werden.

Generatorfunktionen werden im Folgenden beschrieben, während asynchrone Generatorfunktionen separat im Abschnitt Asynchrone Generatorfunktionen behandelt werden.

Wenn eine Generatorfunktion aufgerufen wird, gibt sie einen Iterator zurück, der als Generator bezeichnet wird. Dieser Generator steuert dann die Ausführung der Generatorfunktion. Die Ausführung beginnt, sobald eine der Methoden des Generators aufgerufen wird. Zu diesem Zeitpunkt geht die Ausführung zum ersten yield-Ausdruck über, wo sie erneut angehalten wird und den Wert von yield_list an den Aufrufer des Generators zurückgibt – oder None, falls yield_list weggelassen wurde. Mit unterbrochen ist gemeint, dass der gesamte lokale Zustand beibehalten wird, einschließlich der aktuellen Bindungen lokaler Variablen, des Befehlszeigers, des internen Auswertungsstapels und des Zustands der Ausnahmebehandlung. Wenn die Ausführung durch den Aufruf einer der Methoden des Generators fortgesetzt wird, kann die Funktion genau so weiterlaufen, als wäre der „yield“-Ausdruck lediglich ein weiterer externer Aufruf. Der Wert des yield-Ausdrucks nach der Wiederaufnahme hängt von der Methode ab, die die Ausführung wieder aufgenommen hat. Wird __next__() verwendet (typischerweise entweder über for oder die integrierte Funktion next()), so ist das Ergebnis None. Andernfalls, wenn send() verwendet wird, ist das Ergebnis der an diese Methode übergebene Wert.

All dies macht Generatorfunktionen den Coroutinen sehr ähnlich: Sie führen mehrfach ein „Yield“ aus, verfügen über mehr als einen Einstiegspunkt und ihre Ausführung kann unterbrochen werden. Der einzige Unterschied besteht darin, dass eine Generatorfunktion nicht steuern kann, an welcher Stelle die Ausführung nach einem „Yield“ fortgesetzt werden soll. Die Kontrolle wird stets an den Aufrufer des Generators übergeben.

Yield-Ausdrücke sind an beliebiger Stelle in einem try-Konstrukt zulässig. Wird der Generator nicht wieder aufgenommen, bevor er finalisiert wird (durch Erreichen einer Referenzanzahl von Null oder durch Garbage Collection), wird die Methode close() des Generator-Iterators aufgerufen, wodurch alle ausstehenden finally-Klauseln ausgeführt werden können.

Bei Verwendung von yield from <expr> muss der übergebene Ausdruck ein iterierbares Objekt sein. Die durch die Iteration dieses iterierbaren Objekts erzeugten Werte werden direkt an den Aufrufer der Methoden des aktuellen Generators übergeben. Alle mit send() übergebenen Werte und alle mit throw() übergebenen Ausnahmen werden an den zugrunde liegenden Iterator weitergeleitet, sofern dieser über die entsprechenden Methoden verfügt. Ist dies nicht der Fall, löst send() entweder AttributeError oder TypeError aus, während throw() die übergebene Ausnahme sofort auslöst.

Wenn der zugrunde liegende Iterator abgeschlossen ist, wird das Attribut value der ausgelösten Instanz von StopIteration zum Wert des yield-Ausdrucks. Dieser kann entweder explizit beim Auslösen von StopIteration festgelegt werden oder automatisch, wenn es sich bei dem Unteriterator um einen Generator handelt (durch Rückgabe eines Werts aus dem Untergenerator).

Geändert in Version 3.3: yield from <expr> wurde hinzugefügt, um den Kontrollfluss an einen Subiterator zu delegieren.

Die Klammern können weggelassen werden, wenn der Yield-Ausdruck der einzige Ausdruck auf der rechten Seite einer Zuweisungsanweisung ist.

Siehe auch

PEP 255 - Einfache Generatoren

Der Vorschlag, Generatoren und die Anweisung yield in Python aufzunehmen.

PEP 342 - Coroutinen über erweiterte Generatoren

Der Vorschlag, die API und die Syntax von Generatoren zu verbessern, damit sie als einfache Coroutinen genutzt werden können.

PEP 380 - Syntax für die Delegierung an einen Untergenerator

Der Vorschlag zur Einführung der Syntax yield_from , die die Delegierung an Untergeneratoren vereinfacht.

PEP 525 - Asynchrone Generatoren

Der Vorschlag, der PEP 492 erweiterte, indem er Coroutinen-Funktionen um Generator-Funktionen ergänzte.

6.2.8.1. Beispiele

Hier ist ein einfaches Beispiel, das das Verhalten von Generatoren und Generatorfunktionen veranschaulicht:

>>> def echo(value=None):
...     print("Execution starts when 'next()' is called for the first time.")
...     try:
...         while True:
...             try:
...                 value = (yield value)
...             except Exception as e:
...                 value = e
...     finally:
...         print("Don't forget to clean up when 'close()' is called.")
...
>>> generator = echo(1)
>>> print(next(generator))
Execution starts when 'next()' is called for the first time.
1
>>> print(next(generator))
None
>>> print(generator.send(2))
2
>>> generator.throw(TypeError, "spam")
TypeError('spam',)
>>> generator.close()
Don't forget to clean up when 'close()' is called.

Beispiele für die Verwendung von yield from findest du unter PEP 380: Syntax for Delegating to a Subgenerator im Abschnitt „Neuerungen in Python“.

6.2.8.2. Asynchrone Generatorfunktionen

Das Vorhandensein eines Yield-Ausdrucks in einer Funktion oder Methode, die mit async def definiert wurde, definiert die Funktion zusätzlich als asynchronen Generator.

Wenn eine asynchrone Generatorfunktion aufgerufen wird, gibt sie einen asynchronen Iterator zurück, der als asynchrones Generatorobjekt bezeichnet wird. Dieses Objekt steuert dann die Ausführung der Generatorfunktion. Ein asynchrones Generatorobjekt wird typischerweise in einer async for-Anweisung in einer Coroutine-Funktion verwendet, analog dazu, wie ein Generatorobjekt in einer for-Anweisung verwendet würde.

Der Aufruf einer der Methoden des asynchronen Generators gibt ein awaitable-Objekt zurück, und die Ausführung beginnt, sobald auf dieses Objekt gewartet wird. Dann läuft die Ausführung bis zum ersten yield-Ausdruck, wo sie erneut angehalten wird und der Wert der yield_list an die wartende Coroutine zurückgegeben wird. Wie bei einem Generator bedeutet Anhalten, dass der gesamte lokale Zustand erhalten bleibt – die aktuellen Bindungen der lokalen Variablen, der Befehlszeiger, der interne Auswertungsstapel und der Zustand jeder Ausnahmebehandlung. Wird die Ausführung fortgesetzt, indem auf das nächste von den Methoden des asynchronen Generators zurückgegebene Objekt gewartet wird, kann die Funktion genauso weiterlaufen, als wäre der yield-Ausdruck lediglich ein weiterer externer Aufruf. Welchen Wert der yield-Ausdruck nach dem Fortsetzen hat, hängt von der Methode ab, die die Ausführung fortgesetzt hat. Wird __anext__() verwendet, ist das Ergebnis None. Wird dagegen asend() verwendet, ist das Ergebnis der Wert, der dieser Methode übergeben wurde.

Wenn ein asynchroner Generator vorzeitig beendet wird – sei es durch break , die Abbruch der aufrufenden Aufgabe oder andere Ausnahmen –, wird der asynchrone Bereinigungscode des Generators ausgeführt und löst möglicherweise Ausnahmen aus oder greift auf Kontextvariablen in einem unerwarteten Kontext zu – etwa nach Ablauf der Lebensdauer der Aufgaben, von denen er abhängt, oder während des Herunterfahrens der Ereignisschleife, wenn der Garbage-Collection-Hook des asynchronen Generators aufgerufen wird. Um dies zu verhindern, muss der Aufrufer den asynchronen Generator explizit schließen, indem er die Methode aclose() aufruft, um den Generator zu finalisieren und ihn schließlich von der Ereignisschleife zu trennen.

In einer asynchronen Generatorfunktion sind „yield“-Ausdrücke an jeder Stelle innerhalb eines try-Konstrukts zulässig. Wird ein asynchroner Generator jedoch nicht fortgesetzt, bevor er finalisiert wird (durch Erreichen einer Referenzanzahl von Null oder durch Garbage Collection), kann ein „yield“-Ausdruck innerhalb eines try-Konstrukts dazu führen, dass ausstehende finally-Klauseln nicht ausgeführt werden. In diesem Fall liegt es in der Verantwortung der Ereignisschleife oder des Schedulers, die bzw. der den asynchronen Generator ausführt, die Methode aclose() des asynchronen Generator-Iterators aufzurufen und das resultierende Coroutine-Objekt auszuführen, wodurch die Ausführung aller ausstehenden finally-Klauseln ermöglicht wird.

Um die Finalisierung nach Beendigung der Ereignisschleife zu gewährleisten, sollte eine Ereignisschleife eine finalizer-Funktion definieren, die einen asynchronen Generator-Iterator entgegennimmt und vermutlich aclose() aufruft und die Coroutine ausführt. Dieser finalizer kann durch den Aufruf von sys.set_asyncgen_hooks() registriert werden. Bei der ersten Iteration speichert ein asynchroner Generator-Iterator den registrierten finalizer, der bei der Finalisierung aufgerufen werden soll. Ein Referenzbeispiel für eine finalizer-Methode findest du in der Implementierung von asyncio.Loop.shutdown_asyncgens unter Lib/asyncio/base_events.py.

Der Ausdruck yield from <expr> führt zu einem Syntaxfehler, wenn er in einer asynchronen Generatorfunktion verwendet wird.

6.3. Primäre Funktionen

Primäre Funktionen stellen die am stärksten eingebundenen Operationen der Sprache dar. Ihre Syntax lautet:

primary: atom | attributeref | subscription | call

6.3.1. Attributverweise

Eine Attributreferenz besteht aus einem Primärattribut, gefolgt von einem Punkt und einem Namen:

attributeref: primary "." identifier

Die Primäre Funktion muss zu einem Objekt eines Typs ausgewertet werden, der Attributverweise unterstützt – was bei den meisten Objekten der Fall ist. Dieses Objekt wird dann aufgefordert, das Attribut mit dem Namen des Bezeichners bereitzustellen. Der Typ und der Wert des bereitgestellten Attributs werden vom Objekt bestimmt. Mehrere Auswertungen desselben Attributverweises können zu unterschiedlichen Objekten führen.

Diese Implementierung kann angepasst werden, indem die Methode __getattribute__() oder die Methode __getattr__() überschrieben wird. Die Methode __getattribute__() wird zuerst aufgerufen und gibt entweder einen Wert zurück oder löst eine AttributeError-Ausnahme aus, falls das Attribut nicht verfügbar ist.

Wird eine AttributeError ausgelöst und verfügt das Objekt über eine __getattr__()-Methode, wird diese Methode als Fallback aufgerufen.

6.3.2. Indexierung (Subscriptions) und Slices

Die Syntax subscription (Indexierung) wird in der Regel verwendet, um ein Element aus einem container auszuwählen – beispielsweise, um einen Wert aus einem dict abzurufen

>>> digits_by_name = {'one': 1, 'two': 2}
>>> digits_by_name['two']  # Zugriff auf ein Wörterbuch über den Schlüssel 'two'
2

In der Subscriptions Syntax folgt auf das Objekt, das indiziert wird – ein primäres – ein Index in eckigen Klammern. Im einfachsten Fall handelt es sich bei dem Index um einen einzelnen Ausdruck.

Je nach Art des Objekts, das indiziert wird, wird der Index manchmal als key (bei Zuordnungen), index (bei Sequenzen) oder Typargument (bei generischen Typen) bezeichnet. Syntaktisch sind diese Begriffe alle gleichbedeutend:

>>> colors = ['red', 'blue', 'green', 'black']
>>> colors[3]  # Zugriff auf eine Liste über den Index 3
'black'

>>> list[str]  # Typ list mit dem Typargument str parametrisieren
list[str]

Zur Laufzeit wertet der Interpreter den Primärwert und den Index aus und ruft die Spezialmethode __getitem__() oder __class_getitem__() des Primärwerts mit dem Index als Argument auf. Weitere Informationen dazu, welche dieser Methoden aufgerufen wird, findest du unter __class_getitem__ im Vergleich zu __getitem__.

Um zu veranschaulichen, wie die Indizierung funktioniert, können wir ein benutzerdefiniertes Objekt definieren, das die Schnittstelle __getitem__() implementiert und den Wert von „subscript“ ausgibt:

>>> class SubscriptionDemo:
...     def __getitem__(self, key):
...         print(f'subscripted with: {key!r}')
...
>>> demo = SubscriptionDemo()
>>> demo[1]
subscripted with: 1
>>> demo['a' * 3]
subscripted with: 'aaa'

Informationen dazu, wie integrierte Typen Abonnements verarbeiten, findest du in der Dokumentation unter __getitem__().

Indizes können auch als Ziele in den Anweisungen assignment oder deletion verwendet werden. In diesen Fällen ruft der Interpreter anstelle von __getitem__() jeweils die Spezialmethode __setitem__() oder __delitem__() des mit einem Index versehenen Objekts auf.

>>> colors = ['red', 'blue', 'green', 'black']
>>> colors[3] = 'white'  # Element am Index setzen
>>> colors
['red', 'blue', 'green', 'white']
>>> del colors[3]  # Element an Index 3 löschen
>>> colors
['red', 'blue', 'green']

Alle in den folgenden Abschnitten beschriebenen erweiterten Formen von subscript können auch für die Zuweisung und Löschung verwendet werden.

6.3.2.1. Slicings

Eine fortgeschrittenere Form der Subskription, slicing, wird häufig verwendet, um einen Teil einer Sequenz zu extrahieren. In dieser Form ist das Subskript ein slice: bis zu drei durch Doppelpunkte getrennte Ausdrücke. Jeder der Ausdrücke kann weggelassen werden, aber ein „slice“ muss mindestens einen Doppelpunkt enthalten:

>>> number_names = ['zero', 'one', 'two', 'three', 'four', 'five']
>>> number_names[1:3]
['one', 'two']
>>> number_names[1:]
['one', 'two', 'three', 'four', 'five']
>>> number_names[:3]
['zero', 'one', 'two']
>>> number_names[:]
['zero', 'one', 'two', 'three', 'four', 'five']
>>> number_names[::2]
['zero', 'two', 'four']
>>> number_names[:-3]
['zero', 'one', 'two']
>>> del number_names[4:]
>>> number_names
['zero', 'one', 'two', 'three']

Wenn ein Slice ausgewertet wird, erstellt der Interpreter ein slice-Objekt, dessen Attribute start , stop und step jeweils die Ergebnisse der Ausdrücke zwischen den Doppelpunkten sind. Jeder fehlende Ausdruck wird zu None ausgewertet. Dieses slice-Objekt wird dann wie oben beschrieben an die __getitem__() - oder __class_getitem__()special method-Methode übergeben.

# Weiter geht es mit der oben definierten "SubscriptionDemo“-Instanz:
>>> demo[2:3]
Indizierung mit: slice(2, 3, None)
>>> demo[::'spam']
Indizierung mit: slice(None, None, 'spam')

6.3.2.2. Durch Kommas getrennte Indizes

Der Index kann auch als zwei oder mehr durch Kommas getrennte Ausdrücke oder Ausschnitte angegeben werden:

# Weiter geht es mit der oben definierten Instanz "SubscriptionDemo“:
>>> demo[1, 2, 3]
Indizierung mit: (1, 2, 3)
>>> demo[1:2, 3]
Indizierung mit: (slice(1, 2, None), 3)

Diese Form wird häufig in numerischen Bibliotheken für das Slicing mehrdimensionaler Daten verwendet. In diesem Fall erstellt der Interpreter ein tuple aus den Ergebnissen der Ausdrücke oder Slices und übergibt dieses Tupel wie oben beschrieben an die Spezialmethode __getitem__() beziehungsweise __class_getitem__().

Der Index kann auch als einzelner Ausdruck oder Ausschnitt angegeben werden, gefolgt von einem Komma, um ein Tupel mit einem Element zu definieren:

>>> demo['spam',]
subscripted with: ('spam',)

6.3.2.3. Mit einem Stern markierte Subscriptions

Added in version 3.11: Ausdrücke in tuple_slices können mit einem Sternchen versehen werden. Siehe PEP 646.

Der Index kann auch einen Ausdruck mit Sternchen enthalten. In diesem Fall packt der Interpreter das Ergebnis in ein Tupel aus und übergibt dieses Tupel an __getitem__() oder __class_getitem__()

# Weiter geht es mit der oben definierten Instanz "SubscriptionDemo“:
>>> demo[*range(10)]
Indiziert mit: (0, 1, 2, 3, 4, 5, 6, 7, 8, 9)

Ausdrücke mit Sternchen können mit durch Kommas getrennten Ausdrücken und Slices kombiniert werden:

>>> demo['a', 'b', *range(3), 'c']
subscripted with: ('a', 'b', 0, 1, 2, 'c')

6.3.2.4. Formale Abonnementgrammatik

subscription:     primary '[' subscript ']'
subscript:        single_subscript | tuple_subscript
single_subscript: proper_slice | assignment_expression
proper_slice:     [expression] ":" [expression] [ ":" [expression] ]
tuple_subscript:  ','.(single_subscript | starred_expression)+ [',']

Zur Erinnerung: Der Operator | bezeichnet eine geordnete Auswahl. Konkret gilt bei subscript: Wenn beide Alternativen übereinstimmen, hat die erste (single_subscript) Vorrang.

6.3.3. Calls

Ein Aufruf (Call) ruft ein aufrufbares Objekt (z. B. eine Funktion) mit einer möglicherweise leeren Folge von Argumenten auf:

call:                 primary "(" [argument_list [","] | comprehension] ")"
argument_list:        positional_arguments ["," starred_and_keywords]
                        ["," keywords_arguments]
                      | starred_and_keywords ["," keywords_arguments]
                      | keywords_arguments
positional_arguments: positional_item ("," positional_item)*
positional_item:      assignment_expression | "*" expression
starred_and_keywords: ("*" expression | keyword_item)
                      ("," "*" expression | "," keyword_item)*
keywords_arguments:   (keyword_item | "**" expression)
                      ("," keyword_item | "," "**" expression)*
keyword_item:         identifier "=" expression

Nach den Positions- und Schlüsselwortargumenten kann ein optionales abschließendes Komma stehen, das jedoch keinen Einfluss auf die Semantik hat.

Der Primärausdruck muss zu einem aufrufbaren Objekt ausgewertet werden (benutzerdefinierte Funktionen, integrierte Funktionen, Methoden integrierter Objekte, Klassenobjekte, Methoden von Klasseninstanzen sowie alle Objekte, die über eine Methode __call__() verfügen, sind aufrufbar). Alle Argumentausdrücke werden ausgewertet, bevor der Aufruf versucht wird. Informationen zur Syntax formaler Parameter-Listen findest du im Abschnitt Funktionsdefinitionen .

Sind Schlüsselwortargumente vorhanden, werden diese zunächst wie folgt in Positionsargumente umgewandelt. Zunächst wird eine Liste mit noch nicht belegten Slots für die formalen Parameter erstellt. Gibt es N Positionsargumente, werden diese in die ersten N Slots eingefügt. Anschließend wird für jedes Schlüsselwortargument anhand des Bezeichners der entsprechende Platz bestimmt (stimmt der Bezeichner mit dem Namen des ersten formalen Parameters überein, wird der erste Platz verwendet usw.). Ist der Platz bereits belegt, wird eine Ausnahme vom Typ TypeError ausgelöst. Andernfalls wird das Argument in den Slot gesetzt und füllt diesen aus (selbst wenn der Ausdruck None lautet, füllt er den Slot aus). Wenn alle Argumente verarbeitet wurden, werden die noch unbesetzten Slots mit dem entsprechenden Standardwert aus der Funktionsdefinition gefüllt. (Standardwerte werden einmalig bei der Definition der Funktion berechnet. Daher wird ein veränderbares Objekt wie eine Liste oder ein Wörterbuch, das als Standardwert verwendet wird, von allen Aufrufen gemeinsam genutzt, die keinen Argumentwert für den entsprechenden Slot angeben. Dies sollte in der Regel vermieden werden.) Wenn es ungefüllte Slots gibt, für die kein Standardwert angegeben ist, wird eine Ausnahme vom Typ TypeError ausgelöst. Andernfalls wird die Liste der gefüllten Slots als Argumentliste für den Aufruf verwendet.

Eine Implementierung kann integrierte Funktionen bereitstellen, deren Positionsparameter keine Namen haben – auch wenn sie zu Dokumentationszwecken „benannt“ sind – und die daher nicht per Schlüsselwort übergeben werden können. In CPython ist dies bei Funktionen der Fall, die in C implementiert sind und PyArg_ParseTuple() zum Parsen ihrer Argumente verwenden.

Wenn mehr Positionsargumente vorhanden sind als formale Parameterplätze, wird eine Ausnahme vom Typ TypeError ausgelöst, es sei denn, es ist ein formaler Parameter vorhanden, der die Syntax *identifier verwendet. In diesem Fall erhält dieser formale Parameter ein Tupel, das die überschüssigen Positionsargumente enthält (oder ein leeres Tupel, falls keine überschüssigen Positionsargumente vorhanden waren).

Wenn ein Schlüsselwortargument keinem formalen Parameternamen entspricht, wird eine Ausnahme vom Typ TypeError ausgelöst, es sei denn, es ist ein formaler Parameter vorhanden, der die Syntax **identifier verwendet. In diesem Fall erhält dieser formale Parameter ein Wörterbuch, das die überschüssigen Schlüsselwortargumente enthält (wobei die Schlüsselwörter als Schlüssel und die Argumentwerte als entsprechende Werte dienen), oder ein (neues) leeres Wörterbuch, falls keine überschüssigen Schlüsselwortargumente vorhanden waren.

Wenn die Syntax *expression im Funktionsaufruf vorkommt, muss expression zu einem iterable ausgewertet werden. Elemente aus diesen Iterables werden so behandelt, als wären sie zusätzliche Positionsargumente. Für den Aufruf f(x1, x2, *y, x3, x4) gilt: Wenn y zu einer Sequenz y1, …, yM ausgewertet wird, entspricht dies einem Aufruf mit M+4 Positionsargumenten x1, x2, y1, …, yM, x3, x4.

Dies hat zur Folge, dass die Syntax *expression zwar nach expliziten Schlüsselwortargumenten stehen kann, jedoch vor den Schlüsselwortargumenten (und etwaigen **expression-Argumenten – siehe unten) verarbeitet wird. Also:

>>> def f(a, b):
...     print(a, b)
...
>>> f(b=1, *(2,))
2 1
>>> f(a=1, *(2,))
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: f() got multiple values for keyword argument 'a'
>>> f(1, *(2,))
1 2

Es kommt selten vor, dass sowohl Schlüsselwortargumente als auch die Syntax *expression in ein und demselben Aufruf verwendet werden, sodass diese Verwirrung in der Praxis nicht oft auftritt.

Wenn im Funktionsaufruf die Syntax **expression erscheint, muss expression zu einem mapping ausgewertet werden, dessen Inhalt als zusätzliche Schlüsselwortargumente behandelt wird. Wenn einem Schlüssel bereits ein Wert zugewiesen wurde (durch ein explizites Schlüsselwortargument oder durch eine andere Entpackung), wird eine Ausnahme vom Typ TypeError ausgelöst.

Bei Verwendung von **expression muss jeder Schlüssel in dieser Zuordnung eine Zeichenkette sein. Jeder Wert aus der Zuordnung wird dem ersten formalen Parameter zugewiesen, der für eine Zuweisung über ein Schlüsselwort in Frage kommt und dessen Name mit dem Schlüssel übereinstimmt. Ein Schlüssel muss kein Python-Bezeichner sein (z. B. ist "max-temp °F" zulässig, obwohl er mit keinem formalen Parameter übereinstimmt, der deklariert werden könnte). Wenn keine Übereinstimmung mit einem formalen Parameter vorliegt, wird das Schlüssel-Wert-Paar vom Parameter ** erfasst, sofern vorhanden. Andernfalls wird eine Ausnahme vom Typ TypeError ausgelöst.

Formale Parameter mit der Syntax *identifier oder **identifier dürfen nicht als Positionsargumente oder als Namen für Schlüsselwortargumente verwendet werden.

Geändert in Version 3.5: Funktionsaufrufe akzeptieren eine beliebige Anzahl von * - und **-Entpackungen. Auf iterierbare Entpackungen (*) können Positionsargumente folgen, und auf Dictionary-Entpackungen (**) können Schlüsselwortargumente folgen. Ursprünglich vorgeschlagen von PEP 448.

Ein Aufruf liefert immer einen Wert zurück, gegebenenfalls None, sofern er keine Ausnahme auslöst. Wie dieser Wert berechnet wird, hängt vom Typ des aufrufbaren Objekts ab.

Wenn es so ist—

eine benutzerdefinierte Funktion:

Der Codeblock für die Funktion wird ausgeführt, wobei ihm die Argumentliste übergeben wird. Als Erstes ordnet der Codeblock die formalen Parameter den Argumenten zu. Dies wird im Abschnitt Funktionsdefinitionen beschrieben. Wenn der Codeblock eine Anweisung return ausführt, legt diese den Rückgabewert des Funktionsaufrufs fest. Erreicht die Ausführung das Ende des Codeblocks, ohne dass eine Anweisung return ausgeführt wurde, ist der Rückgabewert None .

eine integrierte Funktion oder Methode:

Das Ergebnis hängt vom Interpreter ab. Unter Integrierte Funktionen findest du Beschreibungen der integrierten Funktionen und Methoden.

ein Klassenobjekt:

Es wird eine neue Instanz dieser Klasse zurückgegeben.

eine Klasseninstanzmethode:

Die entsprechende benutzerdefinierte Funktion wird mit einer Argumentliste aufgerufen, die um ein Element länger ist als die Argumentliste des Aufrufs: Die Instanz wird zum ersten Argument.

eine Klasseninstanz:

Die Klasse muss eine Methode __call__() definieren. Die Auswirkung ist dann dieselbe, als wäre diese Methode aufgerufen worden.

6.4. Ausdruck „Await“

Die Ausführung einer Coroutine für ein awaitable-Objekt unterbrechen. Kann nur innerhalb einer Coroutine-Funktion verwendet werden.

await_expr: "await" primary

Added in version 3.5.

6.5. Der Potenz Operator (Power Operator)

Eine Potenz ist eine kurze Schreibweise für eine mehrfache Multiplikation derselben Zahl.. Der Potenz Operator hat eine stärkere Bindungsstärke als unäre Operatoren zu seiner Linken. Zu seiner Rechten hat er eine geringere Bindungsstärke. Die Syntax lautet:

power: (await_expr | primary) ["**" u_expr]

In einer Kette aus Potenz- und unären Operatoren ohne Klammern werden die Operatoren also von rechts nach links ausgewertet (dies schränkt die Auswertungsreihenfolge der Operanden nicht ein): -1**2 ergibt -1 .

Der Potenzoperator hat dieselbe Semantik wie die integrierte Funktion pow(), wenn er mit zwei Argumenten aufgerufen wird: Er liefert das linke Argument hoch dem rechten Argument. Numerische Argumente werden zunächst in einen gemeinsamen Typ umgewandelt, und das Ergebnis hat diesen Typ.

Bei int-Operanden hat das Ergebnis denselben Typ wie die Operanden, es sei denn, das zweite Argument ist negativ. In diesem Fall werden alle Argumente in float konvertiert und es wird ein float-Ergebnis zurückgegeben. Beispielsweise gibt 10**2 das Ergebnis 100 zurück, während 10**-2 das Ergebnis 0.01 liefert.

Wird 0.0 mit einer negativen Potenz potenziert, ergibt sich ZeroDivisionError . Wird eine negative Zahl mit einer gebrochenen Potenz potenziert, ergibt sich eine complex-Zahl. (In früheren Versionen ergab dies eine ValueError .)

Diese Operation kann mithilfe der speziellen Methoden __pow__() und __rpow__() angepasst werden.

6.6. Unäre Arithmetik und bitweise Operationen

Alle unären arithmetischen und bitweisen Operationen haben dieselbe Priorität:

u_expr: power | "-" u_expr | "+" u_expr | "~" u_expr

Der unäre Operator - (Minus) liefert die Negation seines numerischen Arguments. Die Operation kann mit der speziellen Methode __neg__() überschrieben werden.

Der unäre Operator + (Plus) gibt sein numerisches Argument unverändert zurück. Die Operation kann mit der speziellen Methode __pos__() überschrieben werden.

Der unäre Operator ~ (Invertierung) liefert die bitweise Invertierung seines ganzzahligen Arguments. Die bitweise Invertierung von x ist als -(x+1) definiert. Sie ist nur auf ganze Zahlen anwendbar oder auf eigene Objekte, welche die spezielle Methode __invert__() überschreiben.

In allen drei Fällen wird eine TypeError-Ausnahme ausgelöst, wenn das Argument nicht den richtigen Typ hat.

6.7. Binäre arithmetische Operationen

Die binären arithmetischen Operationen folgen den üblichen Prioritätsstufen. Beachte, dass einige dieser Operationen auch für bestimmte nicht-numerische Typen gelten. Abgesehen vom Potenzoperator gibt es nur zwei Ebenen, eine für multiplikative Operatoren und eine für additive Operatoren:

m_expr: u_expr | m_expr "*" u_expr | m_expr "@" m_expr |
        m_expr "//" u_expr | m_expr "/" u_expr |
        m_expr "%" u_expr
a_expr: m_expr | a_expr "+" m_expr | a_expr "-" m_expr

Der Operator * (Multiplikation) liefert das Produkt seiner Argumente. Entweder müssen beide Argumente Zahlen sein, oder ein Argument ist eine Ganzzahl und das andere eine Sequenz. Im ersten Fall werden die Zahlen in einen gemeinsamen reellen Typ umgewandelt und dann multipliziert. Im zweiten Fall wird die Sequenz wiederholt. Ein negativer Wiederholungsfaktor ergibt eine leere Sequenz.

Diese Operation kann mithilfe der speziellen Methoden „__mul__() und __rmul__() angepasst werden.

Geändert in Version 3.14: Ist nur einer der Operanden eine komplexe Zahl, wird der andere Operand in eine Gleitkommazahl umgewandelt.

Der Operator @ (at) ist für die Matrixmultiplikation vorgesehen. Keiner der integrierten Python-Typen implementiert ihn.

Diese Operation kann mithilfe der speziellen Methoden __matmul__() und __rmatmul__() angepasst werden.

Added in version 3.5.

Die Operatoren / (Division) und // (Abrundungsdivision) liefern den Quotienten ihrer Argumente. Die numerischen Argumente werden zunächst in einen gemeinsamen Typ umgewandelt. Die Division von Ganzzahlen ergibt eine Gleitkommazahl, die Abrundungsdivision von Ganzzahlen dagegen eine Ganzzahl. Das Ergebnis ist das der mathematischen Division, auf das die Funktion „floor“ angewendet wurde. Die Division durch null löst die Ausnahme ZeroDivisionError aus.

Die Division kann mithilfe der speziellen Methoden __truediv__() und __rtruediv__() angepasst werden. Die Rundung nach unten kann mithilfe der speziellen Methoden __floordiv__() und __rfloordiv__() angepasst werden.

Der Modulo-Operator ( % ) liefert den Rest der Division des ersten Arguments durch das zweite. Die numerischen Argumente werden zunächst in einen gemeinsamen Typ konvertiert. Ein rechtes Argument mit dem Wert Null löst die Ausnahme ZeroDivisionError aus. Die Argumente können Gleitkommazahlen sein, z. B. entspricht 3.14%0.7 der 0.34 (da 3.14 der 4*0.7 + 0.34 entspricht). Der Modulo-Operator liefert immer ein Ergebnis mit dem gleichen Vorzeichen wie sein zweiter Operand (oder Null). Der Absolutwert des Ergebnisses ist streng kleiner als der Absolutwert des zweiten Operanden [1].

Die Floor-Division und der Modulo-Operator sind durch die folgende Identität miteinander verbunden: x == (x//y)*y + (x%y). Die Floor-Division und der Modulo-Operator sind außerdem mit der integrierten Funktion divmod() verbunden: divmod(x, y) == (x//y, x%y). [2].

Neben der Durchführung der Modulo-Operation an Zahlen wird der Operator % auch von Zeichenfolgenobjekten überladen, um die Zeichenfolgenformatierung im alten Stil (auch als Interpolation bezeichnet) durchzuführen. Die Syntax für die Zeichenfolgenformatierung wird in der Python-Bibliotheksreferenz im Abschnitt String-Formatierung im printf-Stil beschrieben.

Die Modulo-Operation kann mithilfe der speziellen Methoden __mod__() und __rmod__() angepasst werden.

Der Rundungsoperator, der Modulo-Operator und die Funktion divmod() sind für komplexe Zahlen nicht definiert. Wandle den Wert stattdessen gegebenenfalls mithilfe der Funktion abs() in eine Gleitkommazahl um.

Der Operator + (Addition) liefert die Summe seiner Argumente. Die Argumente müssen entweder beide Zahlen oder beide Sequenzen desselben Typs sein. Im ersten Fall werden die Zahlen in einen gemeinsamen reellen Typ konvertiert und anschließend addiert. Im zweiten Fall werden die Sequenzen aneinandergefügt.

Diese Operation kann mithilfe der speziellen Methoden __add__() und __radd__() angepasst werden.

Geändert in Version 3.14: Ist nur einer der Operanden eine komplexe Zahl, wird der andere Operand in eine Gleitkommazahl umgewandelt.

Der Operator - “(Subtraktion) liefert die Differenz seiner Argumente. Die numerischen Argumente werden zunächst in einen gemeinsamen Real-Typ umgewandelt.

Diese Operation kann mithilfe der speziellen Methoden __sub__() und __rsub__() angepasst werden.

Geändert in Version 3.14: Ist nur einer der Operanden eine komplexe Zahl, wird der andere Operand in eine Gleitkommazahl umgewandelt.

6.8. Verschiebungsoperationen

Die Verschiebungsoperationen haben eine niedrigere Priorität als die arithmetischen Operationen:

shift_expr: a_expr | shift_expr ("<<" | ">>") a_expr

Diese Operatoren akzeptieren Ganzzahlen als Argumente. Sie verschieben das erste Argument um die im zweiten Argument angegebene Anzahl von Bits nach links oder rechts.

Die Linksverschiebung kann mithilfe der speziellen Methoden __lshift__() und __rlshift__() angepasst werden. Die Rechtsverschiebung kann mithilfe der speziellen Methoden __rshift__() und __rrshift__() angepasst werden.

Eine Rechtsverschiebung um n Bit ist als Abrundungsdivision durch pow(2,n) definiert. Eine Linksverschiebung um n Bit ist als Multiplikation mit pow(2,n) definiert.

6.9. Binäre bitweise Operationen

Jede der drei bitweisen Operationen hat eine andere Prioritätsstufe:

and_expr: shift_expr | and_expr "&" shift_expr
xor_expr: and_expr | xor_expr "^" and_expr
or_expr:  xor_expr | or_expr "|" xor_expr

Der Operator & liefert das bitweise UND seiner Argumente, die entweder Ganzzahlen sein müssen oder von denen eines ein benutzerdefiniertes Objekt sein muss, das die speziellen Methoden __and__() oder __rand__() überschreibt.

Der Operator ^ liefert das bitweise XOR (exklusives ODER) seiner Argumente, die Ganzzahlen sein müssen oder von denen eines ein benutzerdefiniertes Objekt sein muss, das die speziellen Methoden __xor__() oder __rxor__() überschreibt.

Der Operator | liefert das bitweise (inklusives) ODER seiner Argumente, bei denen es sich entweder um Ganzzahlen handeln muss oder eines davon ein benutzerdefiniertes Objekt sein muss, das die speziellen Methoden __or__() oder __ror__() überschreibt.

6.10. Vergleiche

Anders als in C haben in Python alle Vergleichsoperationen denselben Vorrang, der niedriger ist als der jeder arithmetischen, verschiebenden oder bitweisen Operation. Ebenfalls anders als in C werden Ausdrücke wie a < b < c so gelesen, wie es in der Mathematik üblich ist:

comparison:    or_expr (comp_operator or_expr)*
comp_operator: "<" | ">" | "==" | ">=" | "<=" | "!="
               | "is" ["not"] | ["not"] "in"

Vergleiche liefern boolesche Werte: True oder False . Benutzerdefinierte erweiterte Vergleichsmethoden können nicht-boolesche Werte zurückgeben. In diesem Fall ruft Python für solche Werte in booleschen Kontexten die Funktion bool() auf.

Vergleiche können beliebig verkettet werden, z. B. ist x < y <= z gleichbedeutend mit x < y and y <= z , mit dem Unterschied, dass y nur einmal ausgewertet wird (in beiden Fällen wird z jedoch überhaupt nicht ausgewertet, wenn x < y als falsch erkannt wird).

Formal gilt: Sind a, b, c, …, y, z Ausdrücke und op1, op2, …, opN Vergleichsoperatoren, dann ist a op1 b op2 c ... y opN z äquivalent zu a op1 b and b op2 c and ... y opN z, mit der Ausnahme, dass jeder Ausdruck höchstens einmal ausgewertet wird.

Beachte, dass „ a op1 b op2 c “ keinerlei Vergleich zwischen a und c impliziert, sodass beispielsweise „ x < y > z “ völlig zulässig ist (wenn auch vielleicht nicht besonders elegant).

6.10.1. Wertvergleiche

Die Operatoren <, >, ==, >=, <= und != vergleichen die Werte zweier Objekte. Die Objekte müssen nicht denselben Typ haben.

In Kapitel Objekte, Werte und Typen heißt es, dass Objekte (neben Typ und Identität) einen Wert haben. Der Wert eines Objekts ist in Python ein eher abstrakter Begriff: So gibt es beispielsweise keine kanonische Zugriffsmethode für den Wert eines Objekts. Außerdem gibt es keine Vorgabe, dass der Wert eines Objekts auf eine bestimmte Weise konstruiert sein muss, z. B. aus all seinen Datenattributen bestehen muss. Vergleichsoperatoren implementieren eine bestimmte Vorstellung davon, was der Wert eines Objekts ist. Man kann sich vorstellen, dass sie den Wert eines Objekts indirekt definieren, und zwar durch ihre Vergleichsimplementierung.

Da alle Typen – direkt oder indirekt – Untertypen von object sind, erben sie das Standardverhalten beim Vergleich von object. Typen können dieses Verhalten anpassen, indem sie erweiterte Vergleichsmethoden wie __lt__() implementieren, beschrieben unter Grundlegende Anpassungen.

Das Standardverhalten beim Gleichheitsvergleich (== und !=) basiert auf der Identität der Objekte. Daher führt der Gleichheitsvergleich von Instanzen mit derselben Identität zu Gleichheit, während der Gleichheitsvergleich von Instanzen mit unterschiedlichen Identitäten zu Ungleichheit führt. Ein Grund für dieses Standardverhalten ist der Wunsch, dass alle Objekte reflexiv sein sollen (d.h., x is y impliziert x == y).

Ein Vergleich der Standardreihenfolge (<, >, <= und >=) ist nicht vorgesehen. Ein entsprechender Versuch löst einen TypeError aus. Ein Grund für dieses Standardverhalten ist das Fehlen einer ähnlichen Invarianten wie bei der Gleichheit.

Das Verhalten des standardmäßigen Gleichheitsvergleichs – wonach Instanzen mit unterschiedlichen Identitäten immer ungleich sind – steht möglicherweise im Widerspruch zu den Anforderungen von Typen, die über eine sinnvolle Definition des Objektwerts und der wertbasierten Gleichheit verfügen. Solche Typen müssen ihr Vergleichsverhalten anpassen, und tatsächlich haben dies bereits eine Reihe von integrierten Typen getan.

Die folgende Liste beschreibt das Vergleichsverhalten der wichtigsten integrierten Datentypen.

  • Zahlen der integrierten numerischen Typen (Numerische Typen — int, float, complex) sowie der Standardbibliotheks-Typen fractions.Fraction und decimal.Decimal können sowohl innerhalb ihres jeweiligen Typs als auch typübergreifend verglichen werden, mit der Einschränkung, dass komplexe Zahlen keinen Reihenfolgevergleich zulassen. Innerhalb der Grenzen der beteiligten Typen erfolgt der Vergleich mathematisch (algorithmisch) korrekt und ohne Genauigkeitsverlust.

    Die Nicht-Zahlen-Werte float('NaN') und decimal.Decimal('NaN') sind Sonderfälle. Jeder geordnete Vergleich einer Zahl mit einem Nicht-Zahlen-Wert ergibt „falsch“. Eine kontraintuitive Folge davon ist, dass Nicht-Zahlen-Werte nicht mit sich selbst gleich sind. Beispielsweise sind die Aussagen x = float('NaN') , 3 < x , x < 3 und x == x alle falsch, während x != x wahr ist. Dieses Verhalten entspricht dem IEEE 754-Standard.

  • None und NotImplemented sind Singletons. PEP 8 empfiehlt, Vergleiche bei Singletons stets mit is oder is not durchzuführen, niemals mit den Gleichheitsoperatoren.

  • Binäre Sequenzen (Instanzen von bytes oder bytearray) lassen sich innerhalb ihres Typs und typübergreifend vergleichen. Verglichen wird lexikografisch anhand der Zahlenwerte ihrer Elemente.

  • Zeichenketten (Instanzen von str) werden lexikografisch anhand der numerischen Unicode-Codepunkte (das Ergebnis der integrierten Funktion ord()) ihrer Zeichen verglichen. [3]

    Zeichenketten und Binärsequenzen lassen sich nicht direkt miteinander vergleichen.

  • Sequenzen (Instanzen von tuple, list oder range) können nur innerhalb ihres jeweiligen Typs verglichen werden, wobei zu beachten ist, dass Bereiche keinen Reihenfolgevergleich unterstützen. Ein Gleichheitsvergleich zwischen diesen Typen führt zu Ungleichheit, und ein Reihenfolgevergleich zwischen diesen Typen löst eine TypeError aus.

    Sequenzen werden lexikografisch verglichen, indem die entsprechenden Elemente miteinander verglichen werden. Die integrierten Container gehen in der Regel davon aus, dass identische Objekte mit sich selbst gleich sind. Dadurch können sie Gleichheitsprüfungen für identische Objekte überspringen, um die Leistung zu verbessern und ihre internen Invarianten aufrechtzuerhalten.

    Der lexikografische Vergleich zwischen den integrierten Sammlungen funktioniert wie folgt:

    • Damit zwei Sammlungen als gleich angesehen werden können, müssen sie denselben Typ und dieselbe Länge haben, und jedes Paar entsprechender Elemente muss als gleich erkannt werden (beispielsweise ist [1,2] == (1,2) falsch, da der Typ nicht derselbe ist).

    • Sammlungen, die den Vergleich von Reihenfolgen unterstützen, werden genauso geordnet wie ihr erstes ungleiches Element (beispielsweise hat [1,2,x] <= [1,2,y] denselben Wert wie x <= y). Wenn kein entsprechendes Element vorhanden ist, wird die kürzere Sammlung zuerst geordnet (beispielsweise ist [1,2] < [1,2,3] wahr).

  • Mappings (Instanzen von dict) sind genau dann gleich, wenn sie gleiche (key, value)-Paare aufweisen. Der Gleichheitsvergleich der Schlüssel und Werte gewährleistet Reflexivität.

    Auftragsvergleiche (<, >, <= und >=) lösen den Fehler TypeError aus.

  • Mengen (Instanzen von set oder frozenset) können sowohl innerhalb ihres Typs als auch typübergreifend verglichen werden.

    Sie definieren Ordnungsvergleichsoperatoren als Tests auf Teilmengen- und Übermengenbeziehungen. Diese Relationen definieren keine Gesamtordnungen (beispielsweise sind die beiden Mengen {1,2} und {2,3} weder gleich, noch sind sie Teilmengen voneinander, noch sind sie Übermengen voneinander). Dementsprechend sind Mengen keine geeigneten Argumente für Funktionen, die von einer totalen Ordnung abhängen (beispielsweise liefern min(), max() und sorted() undefinierte Ergebnisse, wenn eine Liste von Mengen als Eingabe gegeben wird).

    Der Vergleich von Mengen bedingt die Reflexivität ihrer Elemente.

  • Für die meisten anderen integrierten Typen sind keine Vergleichsmethoden implementiert, sodass sie das Standardvergleichsverhalten übernehmen.

Benutzerdefinierte Klassen, die ihr Vergleichsverhalten anpassen, sollten nach Möglichkeit bestimmte Konsistenzregeln befolgen:

  • Der Gleichheitsvergleich sollte reflexiv sein. Mit anderen Worten: Identische Objekte sollten als gleich angesehen werden:

    x is y bedeutet x == y

  • Der Vergleich sollte symmetrisch sein. Mit anderen Worten: Die folgenden Ausdrücke sollten zum gleichen Ergebnis führen:

    x == y und y == x

    x != y und y != x

    x < y und y > x

    x <= y und y >= x

  • Die Vergleichbarkeit sollte transitiv sein. Die folgenden (nicht erschöpfenden) Beispiele veranschaulichen dies:

    x > y and y > z bedeutet x > z

    x < y and y <= z bedeutet x < z

  • Ein inverser Vergleich sollte zur booleschen Negation führen. Mit anderen Worten: Die folgenden Ausdrücke sollten dasselbe Ergebnis liefern:

    x == y und not x != y

    x < y und not x >= y (zum Thema Gesamtordnung)

    x > y und not x <= y (zum Thema Gesamtordnung)

    Die letzten beiden Ausdrücke gelten für vollständig geordnete Mengen (z. B. für Folgen, jedoch nicht für Mengen oder Abbildungen). Siehe auch den Dekorator @~functools.total_ordering .

  • Das Ergebnis von hash() sollte mit der Gleichheit übereinstimmen. Objekte, die gleich sind, sollten entweder denselben Hash-Wert haben oder als „unhashable“ gekennzeichnet sein.

Python erzwingt diese Konsistenzregeln nicht. Tatsächlich sind die „Not-a-Number“-Werte ein Beispiel dafür, dass diese Regeln nicht befolgt werden.

6.10.2. Testbetrieb der Mitgliedschaft

Die Operatoren in und not in prüfen auf Zugehörigkeit. x in s ergibt True, wenn x zu s gehört, und andernfalls False. x not in s gibt die Negation von x in s zurück. Alle integrierten Sequenzen und Mengen-Typen unterstützen dies ebenso wie Wörterbücher, bei denen in prüft, ob das Wörterbuch einen bestimmten Schlüssel enthält. Bei Containertypen wie list, tuple, set, frozenset, dict oder collections.deque ist der Ausdruck x in y gleichbedeutend mit any(x is e or x == e for e in y).

Bei den Typen „String“ und „Bytes“ gilt: x in y ist genau dann True , wenn x ein Teilstring von y ist. Ein gleichwertiger Test ist y.find(x) != -1 . Leere Strings gelten immer als Teilstring jedes anderen Strings, daher gibt "" in "abc" den Wert True zurück.

Bei benutzerdefinierten Klassen, die die Methode __contains__() definieren, gibt x in y den Wert True zurück, wenn y.__contains__(x) einen wahren Wert zurückgibt, und andernfalls den Wert False .

Bei benutzerdefinierten Klassen, die __contains__() nicht definieren, wohl aber __iter__(), ist x in y genau dann True, wenn beim Iterieren über y ein Wert z geliefert wird, für den der Ausdruck x is z or x == z wahr ist. Wird während der Iteration eine Ausnahme ausgelöst, verhält es sich so, als hätte in diese Ausnahme ausgelöst.

Zuletzt wird das alte Iterationsprotokoll versucht: Definiert eine Klasse __getitem__(), ist x in y genau dann True, wenn es einen nicht negativen ganzzahligen Index i gibt, für den x is y[i] or x == y[i] gilt, und kein kleinerer ganzzahliger Index die Ausnahme IndexError auslöst. (Wird eine andere Ausnahme ausgelöst, verhält es sich so, als hätte in diese Ausnahme ausgelöst.)

Der Operator not in ist so definiert, dass er den umgekehrten Wahrheitswert von in hat.

6.10.3. Identitätsvergleiche

Die Operatoren is und is not prüfen die Identität eines Objekts: x is y ist genau dann wahr, wenn x und y dasselbe Objekt sind. Die Identität eines Objekts wird mithilfe der Funktion id() ermittelt. x is not y liefert den umgekehrten Wahrheitswert. [4]

6.11. Boolesche Operationen

or_test:  and_test | or_test "or" and_test
and_test: not_test | and_test "and" not_test
not_test: comparison | "not" not_test

Im Zusammenhang mit booleschen Operationen sowie bei der Verwendung von Ausdrücken in Anweisungen zur Kontrollflusssteuerung werden die folgenden Werte als „falsch“ interpretiert: False , None , die numerische Null aller Typen sowie leere Zeichenketten und Container (einschließlich Zeichenketten, Tupel, Listen, Wörterbücher, Mengen und „frozensets“). Alle anderen Werte werden als „wahr“ interpretiert. Benutzerdefinierte Objekte können ihren Wahrheitswert anpassen, indem sie eine Methode __bool__() bereitstellen.

Der Operator not liefert „ True “, wenn sein Argument falsch ist, andernfalls False .

Der Ausdruck x and y wertet zunächst x aus. Ist x falsch, wird dessen Wert zurückgegeben. Andernfalls wird y ausgewertet und der resultierende Wert zurückgegeben.

Der Ausdruck x or y wertet zunächst x aus. Ist x wahr, wird dessen Wert zurückgegeben. Andernfalls wird y ausgewertet und der resultierende Wert zurückgegeben.

Beachte, dass weder and noch or den Wert und den Typ, den sie zurückgeben, auf False und True beschränken, sondern vielmehr das zuletzt ausgewertete Argument zurückgeben. Dies ist manchmal nützlich, z. B. wenn s eine Zeichenkette ist, die durch einen Standardwert ersetzt werden soll, falls sie leer ist. In diesem Fall liefert der Ausdruck s or 'foo' den gewünschten Wert. Da not einen neuen Wert erzeugen muss, gibt es unabhängig vom Typ seines Arguments einen booleschen Wert zurück (beispielsweise erzeugt not 'foo' False statt '' ).

6.12. Zuweisungsausdrücke

assignment_expression: [identifier ":="] expression

Ein Zuweisungsausdruck (manchmal auch als „benannter Ausdruck“ oder „Walrus“ bezeichnet) weist einem identifier eine expression zu und gibt gleichzeitig den Wert des expression zurück.

Ein häufiger Anwendungsfall ist die Verarbeitung von übereinstimmenden regulären Ausdrücken:

if matching := pattern.search(data):
    do_something(matching)

Oder bei der Verarbeitung eines Dateistroms in Blöcken:

while chunk := file.read(9000):
    process(chunk)

Zuweisungsausdrücke müssen in Klammern gesetzt werden, wenn sie als Ausdrucksanweisungen verwendet werden oder als Unterausdrücke in Slicing-, Bedingungs-, Lambda-, Schlüsselwort-Argument- und Comprehension-if-Ausdrücken sowie in den Anweisungen assert , with und assignment . An allen anderen Stellen, an denen sie verwendet werden können, sind Klammern nicht erforderlich, einschließlich in den Anweisungen if und while .

Added in version 3.8: Weitere Informationen zu Zuweisungsausdrücken findest du unter PEP 572.

6.13. Bedingte Ausdrücke

conditional_expression: or_test ["if" or_test "else" expression]
expression:             conditional_expression | lambda_expr

Ein bedingter Ausdruck (manchmal auch als „ternärer Operator“ bezeichnet) ist eine Alternative zur if-else-Anweisung. Da es sich um einen Ausdruck handelt, gibt er einen Wert zurück und kann als Teilausdruck auftreten.

Der Ausdruck x if C else y wertet zunächst die Bedingung C und nicht x aus. Ist C wahr, wird x ausgewertet und dessen Wert zurückgegeben. Andernfalls wird y ausgewertet und dessen Wert zurückgegeben.

Weitere Informationen zu bedingten Ausdrücken findest du unter PEP 308.

6.14. Lambdas

lambda_expr: "lambda" [parameter_list] ":" expression

Lambda-Ausdrücke (manchmal auch Lambda-Formen genannt) dienen dazu, anonyme Funktionen zu erzeugen. Der Ausdruck lambda parameters: expression liefert ein Funktionsobjekt. Das namenlose Objekt verhält sich wie ein Funktionsobjekt, das so definiert wurde:

def <lambda>(parameters):
    return expression

Informationen zur Syntax von Parameterlisten findest du im Abschnitt Funktionsdefinitionen . Beachte, dass mit Lambda-Ausdrücken erstellte Funktionen keine Anweisungen oder Anmerkungen enthalten dürfen.

6.15. Ausdruckslisten

starred_expression:       "*" or_expr | expression
flexible_expression:      assignment_expression | starred_expression
flexible_expression_list: flexible_expression ("," flexible_expression)* [","]
starred_expression_list:  starred_expression ("," starred_expression)* [","]
expression_list:          expression ("," expression)* [","]
yield_list:               expression_list | starred_expression "," [starred_expression_list]

Sofern sie nicht Teil einer Listen- oder Mengenausgabe ist, ergibt eine Ausdrucksliste, die mindestens ein Komma enthält, ein Tupel. Die Länge des Tupels entspricht der Anzahl der Ausdrücke in der Liste. Die Ausdrücke werden von links nach rechts ausgewertet.

Ein abschließendes Komma ist nur erforderlich, um ein Tupel mit einem Element zu bilden, wie beispielsweise 1,. In allen anderen Fällen ist es optional. Ein einzelner Ausdruck ohne abschließendes Komma bildet kein Tupel, sondern liefert den Wert dieses Ausdrucks. (Um ein leeres Tupel zu bilden, verwende ein leeres Klammerpaar: ().)

6.15.1. Entpacken von Iterables

In einer Ausdrucksliste oder in einem Tupel-, Listen- oder Mengen-Display darf jedem Ausdruck ein Sternchen (*) vorangestellt werden. Das bezeichnet das Entpacken von Iterables.

Zur Laufzeit muss der mit Sternchen versehene Ausdruck zu einem iterable ausgewertet werden. Das Iterable wird zu einer Folge von Elementen ausgebreitet, die an der Stelle des Entpackens in das neue Tupel, die neue Liste oder die neue Menge aufgenommen werden.

Added in version 3.5: Das Entpacken von Iterables in Ausdruckslisten, ursprünglich vorgeschlagen von PEP 448.

Added in version 3.11: Jeder Eintrag in einer Ausdrucksliste kann mit einem Sternchen versehen werden. Siehe PEP 646.

6.16. Bewertungsreihenfolge

Python wertet Ausdrücke von links nach rechts aus. Beachte, dass bei der Auswertung einer Zuweisung die rechte Seite vor der linken Seite ausgewertet wird.

In den folgenden Zeilen werden die Ausdrücke in der arithmetischen Reihenfolge ihrer Suffixe ausgewertet:

expr1, expr2, expr3, expr4
(expr1, expr2, expr3, expr4)
{expr1: expr2, expr3: expr4}
expr1 + expr2 * (expr3 - expr4)
expr1(expr2, expr3, *expr4, **expr5)
expr3, expr4 = expr1, expr2

6.17. Reihenfolge der Rechenoperatoren

Die folgende Tabelle fasst die Operatorpriorität in Python zusammen, von der höchsten Priorität (stärkste Bindung) bis zur niedrigsten Priorität (schwächste Bindung). Operatoren in derselben Spalte haben dieselbe Priorität. Sofern die Syntax nicht ausdrücklich angegeben ist, sind Operatoren binär. Operatoren in derselben Spalte werden von links nach rechts gruppiert (mit Ausnahme von Potenzierung und bedingten Ausdrücken, die von rechts nach links gruppiert werden).

Beachte, dass Vergleichsoperatoren, Zugehörigkeitsprüfungen und Identitätsprüfungen alle dieselbe Priorität haben und eine Verkettung von links nach rechts aufweisen, wie im Abschnitt Vergleiche beschrieben.

Operator

Beschreibung

(expressions...),

[expressions...], {key: value...}, {expressions...}

Gebundener oder in Klammern gesetzter Ausdruck, Listen-Display, Wörterbuch-Display, Mengen-Display

x[index], x[index:index] x(arguments...) , x.attribute

Indexierung (einschließlich Slicing), Aufruf, Attributreferenz

await x

Ausdruck „Await“

**

Potenzieren [5]

+x, -x, ~x

Positiv, negativ, bitweises NOT

*, @, /, //, %

Multiplikation, Matrixmultiplikation, Division, Rundung nach unten, Rest [6]

+, -

Addition und Subtraktion

<<, >>

Verschiebungen

&

Bitweises UND

^

Bitweises XOR

|

Bitweises ODER

in, not in, is, is not, <, <=, >, >=, !=, ==

Vergleiche, einschließlich Zugehörigkeits- und Identitätsprüfungen

nicht x

Boolesches NOT

and

Boolesches UND

or

Boolesches OR

if – else

Bedingter Ausdruck

lambda

Lambda-Ausdruck

:=

Zuweisungsausdruck

Fußnoten