3. Eine informelle Einführung in Python
***************************************

In den folgenden Beispielen werden Eingabe und Ausgabe durch das
Vorhandensein oder Fehlen von Prompts (*>>>* und *...*) unterschieden:
Um das Beispiel nachzuvollziehen, musst du alles eingeben, was nach
dem Prompt steht, sobald dieser erscheint. Zeilen, die nicht mit einem
Prompt beginnen, sind Ausgaben des Interpreters. Beachte, dass ein
zweiter Prompt in einer eigenen Zeile bedeutet, dass du eine Leerzeile
eingeben musst; dies dient dazu, einen mehrzeiligen Befehl zu beenden.

Viele der Beispiele in diesem Handbuch enthalten Kommentare, selbst
wenn sie an der interaktiven Eingabeaufforderung eingegeben werden.
Kommentare beginnen in Python mit dem Raute-Zeichen "#" und erstrecken
sich bis zum Ende der physischen Zeile. Ein Kommentar kann am Anfang
einer Zeile oder nach Leerzeichen oder Code stehen, jedoch nicht
innerhalb eines String-Literals. Ein Raute-Zeichen innerhalb eines
String-Literals ist einfach nur ein Raute-Zeichen. Da Kommentare der
Erklärung von Code dienen und nicht von Python interpretiert werden,
können sie beim Abtippen der Beispiele weggelassen werden.

Einige Beispiele:

   # Dies ist der erste Kommentar
   spam = 1  # und dies ist der zweite Kommentar
             # ... und nun ein dritter!
   text = "# Dies ist kein Kommentar, da es in Anführungszeichen steht."


3.1. Python als Taschenrechner verwenden
========================================

Probieren wir einige einfache Python-Befehle aus. Starte den
Interpreter und warte auf den primären Prompt, ">>>". (Es sollte nicht
lange dauern.)


3.1.1. Zahlen
-------------

Der Interpreter fungiert als einfacher Taschenrechner: Du kannst einen
Ausdruck eingeben, und er gibt den Wert zurück. Die Ausdruckssyntax
ist unkompliziert: Die Operatoren "+", "-", "*" und "/" können für
Rechenoperationen verwendet werden; Klammern ("()") können zum
Gruppieren verwendet werden. Zum Beispiel:

   >>> 2 + 2
   4
   >>> 50 - 5*6
   20
   >>> (50 - 5*6) / 4
   5.0
   >>> 8 / 5  # division always returns a floating-point number
   1.6

Ganzzahlen (z. B. "2", "4", "20") haben den Typ "int", Zahlen mit
Nachkommastellen (z. B. "5.0", "1.6") den Typ "float". Mehr zu
numerischen Typen erfährst du später in diesem Tutorial.

Eine Division ("/") liefert immer eine Gleitkommazahl zurück. Um eine
*Ganzzahldivision* durchzuführen und ein ganzzahliges Ergebnis zu
erhalten, kannst du den Operator "//" verwenden; zur Berechnung des
Restes nutzt du "%":

   >>> 17 / 3  # Klassische Division liefert eine Gleitkommazahl zurück
   5.666666666666667
   >>>
   >>> 17 // 3  # Ganzzahldivision schneidet den Nachkommateil ab
   5
   >>> 17 % 3  # Der %-Operator liefert den Rest der Division zurück
   2
   >>> 5 * 3 + 2  # Abgerundeter Quotient * Divisor + Rest
   17

In Python kann der Operator "**" verwendet werden, um Potenzen zu
berechnen [1]:

   >>> 5 ** 2  # 5 zum Quadrat
   25
   >>> 2 ** 7  # 2 hoch 7
   128

Das Gleichheitszeichen ("=") wird verwendet, um einer Variablen einen
Wert zuzuweisen. Dabei wird vor dem nächsten interaktiven Prompt kein
Ergebnis angezeigt:

   >>> width = 20
   >>> height = 5 * 9
   >>> width * height
   900

Wenn eine Variable nicht „definiert“ ist (ihr kein Wert zugewiesen
wurde), führt der Versuch, diese zu verwenden, zu einem Fehler:

   >>> n  # Versuch, auf eine undefinierte Variable zuzugreifen
   Traceback (most recent call last):
     File "<stdin>", line 1, in <module>
   NameError: name 'n' is not defined

Gleitkommazahlen werden vollständig unterstützt; Operatoren mit
gemischten Operandentypen wandeln den Ganzzahl-Operanden in eine
Gleitkommazahl um:

   >>> 4 * 3.75 - 1
   14.0

Im interaktiven Modus wird der letzte ausgegebene Ausdruck einer
Variablen "_" zugewiesen. Wenn du Python als Taschenrechner nutzt,
erleichtert dies das Weiterrechnen, zum Beispiel:

   >>> tax = 12.5 / 100
   >>> price = 100.50
   >>> price * tax
   12.5625
   >>> price + _
   113.0625
   >>> round(_, 2)
   113.06

Diese Variable sollte vom Benutzer als schreibgeschützt behandelt
werden. Weise ihr nicht explizit einen Wert zu --- du würdest eine
unabhängige lokale Variable desselben Namens erzeugen, die die
integrierte Variable mit ihrem magischen Verhalten verdeckt.

Neben "int" und "float" unterstützt Python weitere Typen von Zahlen,
wie "Decimal" und "Fraction". Python bietet auch integrierte
Unterstützung für komplexe Zahlen und verwendet das Suffix "j" oder
"J", um den Imaginärteil anzugeben (z. B. "3+5j").


3.1.2. Text
-----------

Neben Zahlen kann Python auch Text verarbeiten (dargestellt durch den
Typ "str", sogenannte "Strings" oder Zeichenketten). Dazu gehören
Zeichen ""!"", Wörter ""rabbit"", Namen ""Paris"", Sätze ""Got your
back."" usw. ""Yay! :)"". Sie können in einfache Anführungszeichen
("'...'") oder doppelte Anführungszeichen (""..."") eingeschlossen
werden, mit dem gleichen Ergebnis [2].

   >>> 'spam eggs'  # einfache Anführungszeichen
   'spam eggs'
   >>> "Paris rabbit got your back :)! Yay!"  # doppelte Anführungszeichen
   'Paris rabbit got your back :)! Yay!'
   >>> '1975'  # in Anführungszeichen eingeschlossene Ziffern und Zahlen sind ebenfalls Strings
   '1975'

Um ein Anführungszeichen innerhalb eines Strings zu verwenden, müssen
wir es "maskieren", indem ein "\" vorangestellt wird. Alternativ
können wir die andere Art von Anführungszeichen verwenden:

   >>> 'doesn\'t'  # vergleiche \' zum Maskieren des einfachen Anführungszeichens...
   "doesn't"
   >>> "doesn't"  # ...oder verwende stattdessen doppelte Anführungszeichen
   "doesn't"
   >>> '"Yes," they said.'
   '"Yes," they said.'
   >>> "\"Yes,\" they said."
   '"Yes," they said.'
   >>> '"Isn\'t," they said.'
   '"Isn\'t," they said.'

In der Python-Shell können die String-Definition und die String-
Ausgabe unterschiedlich aussehen. Die Funktion "print()" erzeugt eine
lesbarere Ausgabe, indem sie die umschließenden Anführungszeichen
weglässt und maskierte sowie Sonderzeichen ausgibt:

   >>> s = 'First line.\nSecond line.'  # \n steht für Zeilenumbruch
   >>> s  # ohne print() sind Sonderzeichen im String enthalten
   'First line.\nSecond line.'
   >>> print(s)  # mit print() werden Sonderzeichen interpretiert, sodass \n einen Zeilenumbruch erzeugt
   First line.
   Second line.

Wenn du nicht möchtest, dass Zeichen mit vorangestelltem "\" als
Sonderzeichen interpretiert werden, kannst du *Raw-Strings* verwenden,
indem du ein "r" vor das erste Anführungszeichen setzt:

   >>> print('C:\this\name')  # hier bedeutet \t Tabulator, \n Zeilenumbruch
   C:      his
   ame
   >>> print(r'C:\this\name')  # beachte das r vor dem Anführungszeichen
   C:\this\name

Es gibt einen subtilen Aspekt bei Raw-Strings: Ein Raw-String darf
nicht auf eine ungerade Anzahl von "\"-Zeichen enden; siehe den FAQ-
Eintrag für weitere Informationen und Workarounds.

String-Literale können sich über mehrere Zeilen erstrecken. Eine
Möglichkeit ist die Verwendung von dreifachen Anführungszeichen:
""""..."""" oder "'''...'''". Zeilenendzeichen werden automatisch in
den String eingeschlossen, aber es ist möglich, dies zu verhindern,
indem ein "\" am Ende der Zeile angefügt wird. Im folgenden Beispiel
ist der einleitende Zeilenumbruch nicht enthalten:

   >>> print("""\
   ... Usage: thingy [OPTIONS]
   ...      -h                        Display this usage message
   ...      -H hostname               Hostname to connect to
   ... """)
   Usage: thingy [OPTIONS]
        -h                        Display this usage message
        -H hostname               Hostname to connect to

   >>>

Strings können mit dem Operator "+" verknüpft (zusammengefügt) und mit
"*" wiederholt werden:

   >>> # 3-mal 'un', gefolgt von 'ium'
   >>> 3 * 'un' + 'ium'
   'unununium'

Zwei oder mehr *String-Literale* (also solche in Anführungszeichen),
die nebeneinanderstehen, werden automatisch verknüpft.

   >>> 'Py' 'thon'
   'Python'

Dieses Feature ist besonders nützlich, wenn du lange Strings umbrechen
möchtest:

   >>> text = ('Setze mehrere Strings in Klammern, '
   ...         'um sie zusammenzufügen.')
   >>> text
   'Setze mehrere Strings in Klammern, um sie zusammenzufügen.'

Dies funktioniert jedoch nur mit zwei Literalen, nicht mit Variablen
oder Ausdrücken:

   >>> prefix = 'Py'
   >>> prefix 'thon'  # Variable und String-Literal können so nicht verknüpft werden
     File "<stdin>", line 1
       prefix 'thon'
              ^^^^^^
   SyntaxError: invalid syntax
   >>> ('un' * 3) 'ium'
     File "<stdin>", line 1
       ('un' * 3) 'ium'
                  ^^^^^
   SyntaxError: invalid syntax

Wenn du Variablen oder eine Variable und ein Literal verknüpfen
möchtest, verwende "+":

   >>> prefix + 'thon'
   'Python'

Strings können *indiziert* werden (mit Index), wobei das erste Zeichen
den Index 0 hat. Es gibt keinen eigenen Zeichentyp; ein Zeichen ist
einfach ein String der Länge eins:

   >>> word = 'Python'
   >>> word[0]  # Zeichen an Position 0
   'P'
   >>> word[5]  # Zeichen an Position 5
   'n'

Indizes können auch negative Zahlen sein, um von rechts zu zählen:

   >>> word[-1]  # letztes Zeichen
   'n'
   >>> word[-2]  # vorletztes Zeichen
   'o'
   >>> word[-6]
   'P'

Beachte, dass negative Indizes bei -1 beginnen, da -0 dasselbe wie 0
ist.

Neben dem Indizieren wird auch *Slicing* (Ausschneiden) unterstützt.
Während Indizieren dazu dient, einzelne Zeichen zu erhalten,
ermöglicht *Slicing* das Heraustrennen eines Teilstrings:

   >>> word[0:2]  # Zeichen von Position 0 (einschließlich) bis 2 (ausschließlich)
   'Py'
   >>> word[2:5]  # Zeichen von Position 2 (einschließlich) bis 5 (ausschließlich)
   'tho'

Slice-Indizes haben nützliche Standardwerte; ein ausgelassener erster
Index wird standardmäßig auf null gesetzt, ein ausgelassener zweiter
Index entspricht standardmäßig der Länge des verwendeten Strings.

   >>> word[:2]   # Zeichen vom Anfang bis Position 2 (ausschließlich)
   'Py'
   >>> word[4:]   # Zeichen von Position 4 (einschließlich) bis zum Ende
   'on'
   >>> word[-2:]  # Zeichen vom Vorletzten (einschließlich) bis zum Ende
   'on'

Beachte, dass der Startwert immer eingeschlossen und der Endwert immer
ausgeschlossen ist. Dies stellt sicher, dass "s[:i] + s[i:]" immer
gleich "s" ist:

   >>> word[:2] + word[2:]
   'Python'
   >>> word[:4] + word[4:]
   'Python'

Eine Möglichkeit, sich die Funktionsweise von Slices zu merken,
besteht darin, sich die Indizes so vorzustellen, dass sie *zwischen*
die Zeichen zeigen, wobei die linke Kante des ersten Zeichens die
Nummer 0 hat. Die rechte Kante des letzten Zeichens eines Strings mit
*n* Zeichen hat dann den Index *n*, zum Beispiel:

    +---+---+---+---+---+---+
    | P | y | t | h | o | n |
    +---+---+---+---+---+---+
    0   1   2   3   4   5   6
   -6  -5  -4  -3  -2  -1

Die erste Zahlenreihe gibt die Position der Indizes 0...6 im String
an, die zweite Reihe zeigt die entsprechenden negativen Indizes. Der
Slice von *i* bis *j* besteht aus allen Zeichen zwischen den mit *i*
bzw. *j* beschrifteten Kanten.

Für nicht-negative Indizes ist die Länge eines Slices die Differenz
der Indizes, sofern beide innerhalb der Grenzen liegen. Zum Beispiel
beträgt die Länge von "word[1:3]" 2.

Der Versuch, einen zu großen Index zu verwenden, führt zu einem
Fehler:

   >>> word[42]  # das Wort hat nur 6 Zeichen
   Traceback (most recent call last):
     File "<stdin>", line 1, in <module>
   IndexError: string index out of range

Außerhalb des Bereichs liegende Slice-Indizes werden beim Slicing
jedoch toleriert:

   >>> word[4:42]
   'on'
   >>> word[42:]
   ''

Python-Strings können nicht verändert werden --- sie sind
*unveränderlich*. Zuweisungen an eine indizierte Position im String
führen daher zu einem Fehler:

   >>> word[0] = 'J'
   Traceback (most recent call last):
     File "<stdin>", line 1, in <module>
   TypeError: 'str' object does not support item assignment
   >>> word[2:] = 'py'
   Traceback (most recent call last):
     File "<stdin>", line 1, in <module>
   TypeError: 'str' object does not support item assignment

Wenn du einen anderen String benötigst, solltest du einen neuen
erstellen:

   >>> 'J' + word[1:]
   'Jython'
   >>> word[:2] + 'py'
   'Pypy'

Die integrierte Funktion "len()" gibt die Länge eines Strings zurück:

   >>> s = 'supercalifragilisticexpialidocious'
   >>> len(s)
   34

Siehe auch:

  Textsequenztyp – str
     Strings sind Beispiele für *Sequenztypen* und unterstützen die
     für solche Typen üblichen Operationen.

  String-Methoden
     Strings unterstützen eine Vielzahl von Methoden für grundlegende
     Umwandlungen und Suchen.

  f-Strings
     String-Literale, die eingebettete Ausdrücke enthalten.

  Syntax für Formatzeichenketten
     Informationen zur Formatierung von Strings mit "str.format()".

  String-Formatierung im printf-Stil
     Die alten Formatierungsoperationen, die aufgerufen werden, wenn
     Strings der linke Operand des "%"-Operators sind, werden hier
     ausführlicher beschrieben.


3.1.3. Listen
-------------

Python kennt eine Reihe von *zusammengesetzten* Datentypen, die
verwendet werden, um andere Werte zusammenzufassen. Der vielseitigste
ist die *Liste*, die als durch Kommas getrennte Liste von Werten
(Elementen) in eckigen Klammern geschrieben werden kann. Listen können
Elemente verschiedener Typen enthalten, meist haben die Elemente
jedoch denselben Typ.

   >>> squares = [1, 4, 9, 16, 25]
   >>> squares
   [1, 4, 9, 16, 25]

Wie Strings (und alle anderen integrierten *Sequenztypen*) können
Listen indiziert und zerteilt werden:

   >>> squares[0]  # Indizierung gibt das Element zurück
   1
   >>> squares[-1]
   25
   >>> squares[-3:]  # Slicing gibt eine neue Liste zurück
   [9, 16, 25]

Listen unterstützen auch Operationen wie die Verkettung:

   >>> squares + [36, 49, 64, 81, 100]
   [1, 4, 9, 16, 25, 36, 49, 64, 81, 100]

Im Gegensatz zu Strings, die *unveränderlich* sind, sind Listen ein
*veränderlicher* Typ, d. h. ihr Inhalt kann geändert werden:

   >>> cubes = [1, 8, 27, 65, 125]  # Hier stimmt etwas nicht
   >>> 4 ** 3  # Die dritte Potenz von 4 ist 64, nicht 65!
   64
   >>> cubes[3] = 64  # Ersetze den falschen Wert
   >>> cubes
   [1, 8, 27, 64, 125]

Du kannst auch neue Elemente am Ende der Liste hinzufügen, indem du
die "list.append()" *Methode* verwenden (mehr zu Methoden werden wir
später sehen):

   >>> cubes.append(216)  # Füge die dritte Potenz von 6 hinzu
   >>> cubes.append(7 ** 3)  # und die dritte Potenz von 7
   >>> cubes
   [1, 8, 27, 64, 125, 216, 343]

Eine einfache Zuweisung kopiert in Python niemals Daten. Wenn du eine
Liste einer Variablen zuweisen, bezieht sich die Variable auf die
*bestehende Liste*. Alle Änderungen, die du an der Liste über eine
Variable vornimmst, sind über alle anderen Variablen sichtbar, die
sich auf sie beziehen.:

   >>> rgb = ["Red", "Green", "Blue"]
   >>> rgba = rgb
   >>> id(rgb) == id(rgba)  # Sie verweisen auf dasselbe Objekt
   True
   >>> rgba.append("Alph")
   >>> rgb
   ["Red", "Green", "Blue", "Alph"]

Alle Slicing-Operationen geben eine neue Liste zurück, die die
angeforderten Elemente enthält. Das bedeutet, dass das folgende
Slicing eine flache Kopie der Liste zurückgibt:

   >>> correct_rgba = rgba[:]
   >>> correct_rgba[-1] = "Alpha"
   >>> correct_rgba
   ["Red", "Green", "Blue", "Alpha"]
   >>> rgba
   ["Red", "Green", "Blue", "Alph"]

Zuweisungen an Slices sind ebenfalls möglich, und dies kann sogar die
Größe der Liste verändern oder sie vollständig leeren:

   >>> letters = ['a', 'b', 'c', 'd', 'e', 'f', 'g']
   >>> letters
   ['a', 'b', 'c', 'd', 'e', 'f', 'g']
   >>> # Ersetze einige Werte
   >>> letters[2:5] = ['C', 'D', 'E']
   >>> letters
   ['a', 'b', 'C', 'D', 'E', 'f', 'g']
   >>> # Entferne sie jetzt
   >>> letters[2:5] = []
   >>> letters
   ['a', 'b', 'f', 'g']
   >>> # Leere die Liste, indem alle Elemente durch eine leere Liste ersetzt werden
   >>> letters[:] = []
   >>> letters
   []

Die integrierte Funktion "len()" lässt sich auch auf Listen anwenden:

   >>> letters = ['a', 'b', 'c', 'd']
   >>> len(letters)
   4

Es ist möglich, Listen zu verschachteln (Listen zu erstellen, die
andere Listen enthalten), zum Beispiel:

   >>> a = ['a', 'b', 'c']
   >>> n = [1, 2, 3]
   >>> x = [a, n]
   >>> x
   [['a', 'b', 'c'], [1, 2, 3]]
   >>> x[0]
   ['a', 'b', 'c']
   >>> x[0][1]
   'b'


3.2. Erste Schritte in Richtung Programmierung
==============================================

Natürlich können wir Python für kompliziertere Aufgaben nutzen als
zwei und zwei zusammenzuzählen. Zum Beispiel können wir eine
anfängliche Teilfolge der Fibonacci-Folge wie folgt schreiben:

   >>> # Fibonacci-Folge:
   >>> # Die Summe zweier Elemente ergibt das nächste
   >>> a, b = 0, 1
   >>> while a < 10:
   ...     print(a)
   ...     a, b = b, a+b
   ...
   0
   1
   1
   2
   3
   5
   8

Dieses Beispiel führt einige neue Funktionen ein.

* Die erste Zeile enthält eine *Mehrfachzuweisung*: Die Variablen "a"
  und "b" erhalten gleichzeitig die neuen Werte 0 und 1. In der
  letzten Zeile wird dies erneut verwendet, was zeigt, dass die
  Ausdrücke auf der rechten Seite alle zuerst ausgewertet werden,
  bevor irgendeine Zuweisung stattfindet. Die Ausdrücke auf der
  rechten Seite werden von links nach rechts ausgewertet.

* Die "while"-Schleife wird ausgeführt, solange die Bedingung (hier:
  "a < 10") wahr bleibt. In Python ist, wie in C, jeder Ganzzahlwert
  ungleich Null wahr; Null ist falsch. Die Bedingung kann auch ein
  String- oder Listenwert sein, tatsächlich jede Sequenz, alles mit
  einer Länge ungleich Null ist wahr, leere Sequenzen sind falsch. Der
  im Beispiel verwendete Test ist ein einfacher Vergleich. Die
  Standard-Vergleichsoperatoren werden genauso geschrieben wie in C:
  "<" (kleiner als), ">" (größer als), "==" (gleich), "<=" (kleiner
  oder gleich), ">=" (größer oder gleich) und "!=" (ungleich).

* Der *Rumpf* der Schleife ist *eingerückt*: Einrückung ist Pythons
  Methode, um Anweisungen zu gruppieren. An der interaktiven
  Eingabeaufforderung musst du für jede eingerückte Zeile einen
  Tabulator oder Leerzeichen eingeben. In der Praxis wirst du
  kompliziertere Eingaben für Python mit einem Texteditor vorbereiten;
  alle guten Texteditoren verfügen über eine automatische Einrückung.
  Wenn eine zusammengesetzte Anweisung interaktiv eingegeben wird,
  muss ihr eine Leerzeile folgen, um den Abschluss anzuzeigen (da der
  Parser nicht erraten kann, wann du die letzte Zeile eingegeben
  hast). Beachte, dass jede Zeile innerhalb eines Basisblocks um
  denselben Abstand eingerückt sein muss.

* Die Funktion "print()" gibt den Wert des oder der übergebenen
  Argumente aus. Sie unterscheidet sich vom bloßen Schreiben des
  Ausdrucks (wie wir es vorhin in den Rechnerbeispielen getan haben)
  durch die Art und Weise, wie sie mit mehreren Argumenten,
  Gleitkommazahlen und Strings umgeht. Strings werden ohne
  Anführungszeichen ausgegeben, und zwischen den Elementen wird ein
  Leerzeichen eingefügt, sodass du Dinge schön formatieren kannst, wie
  hier:

     >>> i = 256*256
     >>> print('Der Wert von i ist', i)
     Der Wert von i ist 65536

  Das Schlüsselwort-Argument *end* kann verwendet werden, um den
  Zeilenumbruch nach der Ausgabe zu verhindern oder die Ausgabe mit
  einer anderen Zeichenkette zu beenden:

     >>> a, b = 0, 1
     >>> while a < 1000:
     ...     print(a, end=',')
     ...     a, b = b, a+b
     ...
     0,1,1,2,3,5,8,13,21,34,55,89,144,233,377,610,987,

-[ Fußnoten ]-

[1] Da "**" eine höhere Rangfolge als "-" hat, wird "-3**2" als
    "-(3**2)" interpretiert und führt somit zu "-9". Um dies zu
    vermeiden und "9" zu erhalten, kannst du "(-3)**2" verwenden.

[2] Anders als in anderen Sprachen haben Sonderzeichen wie "\n" sowohl
    bei einfachen ("'...'") als auch bei doppelten (""..."")
    Anführungszeichen dieselbe Bedeutung. Der einzige Unterschied
    besteht darin, dass du innerhalb einfacher Anführungszeichen """
    nicht maskieren musst (dafür aber "\'") und umgekehrt.
