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:

* "()" (runde Klammern): Gruppen, Tupel-Displays, yield-Atoms und
  Generatorausdrücke;

* "[]" (eckige Klammern): Listen-Displays;

* "{}" (geschweifte Klammern): Wörterbuch-Displays und Mengen-
  Displays.

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 When can I rely on identity
tests with the is operator?.

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: | Gebundener oder in Klammern gesetzter |
| value...}", "{expressions...}"                  | Ausdruck, Listen-Display, Wörterbuch- |
|                                                 | Display, Mengen-Display               |
+-------------------------------------------------+---------------------------------------+
| "x[index]", "x[index:index]" "x(arguments...)"  | Indexierung (einschließlich Slicing), |
| , "x.attribute"                                 | 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 ]-

[1] Zwar gilt „ "abs(x%y) < abs(y)" “ mathematisch gesehen, doch bei
    Fließkommazahlen trifft dies aufgrund von Rundungsfehlern
    numerisch möglicherweise nicht zu. Nehmen wir beispielsweise an,
    dass auf einer Plattform, auf der ein Python-Fließkommawert eine
    IEEE-754-Zahl mit doppelter Genauigkeit ist, das berechnete
    Ergebnis „ "-1e-100 + 1e100" “ lautet, damit „ "-1e-100 % 1e100" “
    dasselbe Vorzeichen wie „ "1e100" “ hat. Dies entspricht numerisch
    genau „ "1e100" “.  Die Funktion „ "math.fmod()" “ gibt
    stattdessen ein Ergebnis zurück, dessen Vorzeichen mit dem
    Vorzeichen des ersten Arguments übereinstimmt, und liefert in
    diesem Fall daher „ "-1e-100" “. Welcher Ansatz besser geeignet
    ist, hängt von der jeweiligen Anwendung ab.

[2] Wenn x sehr nahe an einem exakten ganzzahligen Vielfachen von y
    liegt, kann es aufgrund von Rundungen vorkommen, dass "x//y" um
    eins größer ist als "(x-x%y)//y". In solchen Fällen gibt Python
    das letztere Ergebnis zurück, damit weiterhin gilt, dass
    "divmod(x,y)[0] * y + x % y" sehr nahe an "x" liegt.

[3] Der Unicode-Standard unterscheidet zwischen *Codepunkten* (z. B.
    U+0041) und *abstrakten Zeichen* (z. B. „LATIN CAPITAL LETTER A“).
    Während die meisten abstrakten Zeichen in Unicode nur durch einen
    einzigen Codepunkt dargestellt werden, gibt es eine Reihe von
    abstrakten Zeichen, die zusätzlich durch eine Folge von mehr als
    einem Codepunkt dargestellt werden können. Beispielsweise kann das
    abstrakte Zeichen „LATIN CAPITAL LETTER C WITH CEDILLA“ als
    einzelnes *vorkomponiertes Zeichen* an der Codeposition U+00C7
    oder als Folge aus einem *Basiszeichen* an der Codeposition U+0043
    (LATIN CAPITAL LETTER C), gefolgt von einem *Kombinationszeichen*
    an der Codeposition U+0327 (COMBINING CEDILLA).

    Die Vergleichsoperatoren für Zeichenketten vergleichen auf der
    Ebene der Unicode-Codepunkte. Dies mag für Menschen zunächst nicht
    intuitiv erscheinen. Beispielsweise ist „ ""\u00C7" ==
    "\u0043\u0327"" “ gleichbedeutend mit „ "False" “, obwohl beide
    Zeichenketten dasselbe abstrakte Zeichen „LATIN CAPITAL LETTER C
    WITH CEDILLA“ darstellen.

    Um Zeichenketten auf der Ebene abstrakter Zeichen zu vergleichen
    (d.h. auf eine für Menschen intuitive Weise), verwende
    "unicodedata.normalize()".

[4] Aufgrund der automatischen Speicherbereinigung, der Freilisten und
    der dynamischen Natur von Deskriptoren kann es bei bestimmten
    Anwendungen des Operators „ "is" “ – beispielsweise bei
    Vergleichen zwischen Instanzmethoden oder Konstanten – zu
    scheinbar ungewöhnlichem Verhalten kommen. Weitere Informationen
    findest du in der entsprechenden Dokumentation.

[5] Der Potenzoperator "**" bindet weniger streng als ein
    arithmetischer oder bitweiser unärer Operator zu seiner Rechten,
    das heißt: "2**-1" ergibt "0.5".

[6] Der Operator „ "%" “ wird ebenfalls zur Formatierung von
    Zeichenketten verwendet. Es gilt dieselbe Priorität.
