-->

Variablen und Datentypen



Variablennamen

Ein Variablenname kann grundsätzlich beliebig lang sein, unterliegt aber gewissen Bedingungen:

  • Der Name muss mit einem Buchstaben oder dem Unterstrich (underscore) beginnen; eine Ziffer am Anfang ist beispielsweise nicht erlaubt.
  • Der Name darf nur alphanumerische Zeichen und den Unterstrich enthalten (A-Z, a-z, 0-9 und _ )
  • Variablennamen unterscheiden Groß/Kleinschreibung, sie sind case sensitive. "Var", "VAR" und "var" sind daher drei verschiedene Variablen.
  • Er sollte unterschiedlich zu den intern vergebenen Namen (Keywords) sein. Vergeben sind bereits:

    import keyword # alle vergebenen Namen
    print(keyword.kwlist) 
  • Der Typ None

    Eine Variable kann nicht deklariert werden, ohne dass ihr ein Wert (Typ) zugewiesen wird. Ist dies der Fall, bekommt sie den "Typ" undefined zugewiesen und verursacht einen Fehler:

    var_0 # NICHT definiert! -> Fehler!!
    var_1 = None # definiert, aber ohne sinnvollen Typ/Wert
    var_2 = 2
    print("Ausgabe der Typen: ", type(var_1), type(var_2))

    Übung: Modifizieren Sie obiges Beispiel derart, dass es ohne Fehler durchläuft. Die erste Zeile darf dabei nicht gelöscht werden. Hinweis: Rechts von dem Kommentarzeichen # wird alles ignoriert.

    Der Typ None entspricht einer Konstanten und kann für Abfragen benutzt werden, um festzustellen, ob einer Variablen ein neuer Wert zugewiesen wurde:

    var_1 = "hat einen Wert"
    if var_1 is None:
      print('var_1 hat keinen Wert.')
    else:
      print('Der Wert von var_1 ist ', var_1)
      print('und der Typ ist ', type(var_1))

    Übung: Testen Sie obiges Beispiel für die Definition var_1 = None!

    Wenn Sie Informationen zum if-Konstrukt wüschen, so gehen Sie zur zweiten Kurseinheit.


    Der Typ Bool

    Boolesche Variablen können die Werte False oder True annehmen, wobei Python die Zahl 1, beziehungsweise die Zahl 0 als True, beziehungsweise False, interpretiert. Dadurch ist True + True eine zulässige Operation und ergibt 2. Grundsätzlich ist jede Ganzzahl größer als 0 True. Dieser formale Wahrheitswert kann mithilfe der Standardfunktion bool() ermittelt werden.

    var_1 = 177
    var_2 = 13
    print(bool(var_1 + var_2))

    Übung: Testen Sie, was sích für bool(var_1 * var_2), bool(var_1/var_2) und bool(var_1//var_2) ergibt!

    Zusammenfassung und Übungen

    Der Typ int –- Ganze Zahlen

    Ganzzahlige Werte werden in Python durch den Datentyp int repräsentiert. Eine frühere Unterscheidung in int und longint existiert nicht mehr. Die Größe eines int war in Python 2 auf 32 Bit begrenzt. Ganzzahlen waren daher im Bereich von -2.147.483.648 bis 2.147.483.647 möglich. Ein longint erlaubte den Bereich -9.223.372.036.854.775.808 bis 9.223.372.036.854.775.807. In Python 3 ist der lange Datentyp nicht mehr vorhanden und außerdem ein aktualisiertes int, welches eine beliebige Größe haben kann! Dies ist in fast allen anderen Programmiersprachen nicht möglich. Trotzdem kann es zu langen Rechenzeiten kommen, wenn man mit "bombastischen" Zahlen rechnet. Wir zeigen das am Beispiel der Berechnung einer Fakultät: n!=1*2*3*4*...*n

    Um die Anzahl an Ziffern einer Ganzzahl zu bestimmen, kann diese zuerst mit der Standardfunktion str() (string) in eine Zeichenkette umgewandelt werden. Von dieser lässt sich anschließend mit der Standardfunktion len() (length) die Länge (Anzahl der Zeichen) bestimmt werden. Beides kann auch in einem Schritt erfolgen:

    k = 1 # Startwert
    maxN = 1000
    for i in range(1, maxN): # Bereich 1,2,3,...maxN-1
      k = k * i              # n-1*n
      #print(k)              # Die Zahl n!
      print(len(str(k)))     # Anzahl Ziffern

    Übung: Testen Sie, ob sich für maxN = 10000 längere Rechenzeiten ergeben!
    Für Fortgeschrittene: Testen Sie, ob es ein n! mit genau 12345 Stellen gibt.

    Lösung siehe hier.

    Wird in obigem Beispiel die Maximalzahl erst durch eine Eingabe über input() vorgegeben, so ist zu beachten, dass sie dann formal als Zeichenkette (String) und nicht als Zahl existiert; es können nur Zeichenketten eingelsen werden! Mit der Standardfunktion int() ist dann aber eine Konvertierung in eine Ganzzahl möglich. Das folgende Beispiel kann nur auf dem eigenen Rechner ausgeführt werden, da die meisten Online-Compiler keine interaktiven Aktionen erlauben.

    k = 1 # Startwert
    #maxN = input("Max= ")   #   auf der Webseite nicht möglich
    maxN = 100
    for i in range(1, int(maxN)): # Bereich 1,2,3,...maxN-1
      k = k * i              # n-1*n
      #print(k)              # Die Zahl n!
      print(len(str(k)))     # Anzahl Ziffern

    Standardmäßig werden Ganzzahlen im üblichen Zehnersystem ausgegeben. Es ist aber auch eine einfache Wandlung der Zahlen in binärer (Basis 2), oktaler (Basis 8)oder hexadezimaler (Basis 16) Darstellung möglich, wie sie vielfach in Programmen für Interna von Computern benötigt werden. Die entsprechenden Standardfunktionen zeigt das folgende Beispiel, wobei zu beachten ist, dass wegen des Zeichenpräfixes zur Festlegung der Basis die Ausgaben dann Zeichenketten sind.:

    Zahl = 65535
    print(Zahl)
    print(hex(Zahl))
    print(oct(Zahl))
    print(bin(Zahl))

    0x steht für Hexadezimal, 0o für Oktal und 0b für Binär. Eine Rückwandlung in eine Dezimalzahl ist dann wieder über die Standardfunktion int() möglich. Die Angabe des jeweiligen Präfixes kann entfallen, da zwingend als zweiter Parameter die Basis angegeben werden muss:

    Zahl = 65535
    Hex = hex(Zahl)
    Oct = oct(Zahl)
    Bin = bin(Zahl)
    print(Hex, int(Hex,base=16))
    print(Oct, int(Oct,base=8))
    print(Bin, int(Bin,base=2))
    print(int('0xFFFF',base=16))# Eingabe als Zeichenkette
    print(int('FFFF',base=16))  #    "     "       "

    Weitere Standardfunktionen für Ganzzahlen (Integer) sind min() und max(), welche von einer Zahlenliste den kleinsten, beziehungsweise größten Wert zurückgeben, sowie die Funktion abs(), welche den Absolutwert (Betrag) einer Zahl zurückgibt. Alle drei Funktionen können auch für Gleitkommazahlen (Float) angewendet werden:

    print(min(1, 4, -3, 15, -3.1))
    print(max(1, 4, -3, 15, -3.1))
    print(abs(min(1, 4, -3, 15, -3.1)))
    

    Der Typ float –- Gleitkommazahlen (floating numbers)

    Dezimalzahlen werden in vielen Programmiersprachen, so auch in Python durch den Datentyp float repräsentiert. Die Nachkommastellen werden dabei – wie im englischen Sprachraum üblich – durch einen Punkt von dem ganzzahligen Anteil getrennt. Große oder sehr kleine Dezimalzahlen lassen sich in der Exponentialschreibweise angeben. 1.2e3 steht dann für 1.2*103. Die Ausgabe von Gleitkommazahlen ist dabei nicht ganz konsequent, wie man im folgenden Beispiel sieht. Mal gibt es die Ausgabe als Gleitkommazahl und mal nicht. Es existieren die üblichen Rundungsfunktionen wie round() und int(), wobei erstere ohne Angabe eines zweiten Parameters auf die nächste ganze Zahl rundet. Mit dem zweiten Parameter kann auf n Nachkommastellen gerundet werden. Mit int() wird einfach der Nachkommateil abgeschnitten. In anderen Programmiersprachen auch als trunc bezeichnet.

    print(" 0: ", -1e-1)
    print(" 1: ", 1/1e12)
    print(" 2: ", 1/1e-12)
    print(" 3: ", 1.23e2/1.1e2)
    print(" 4: ", round(1.23e2/1.1e2))    # nächste ganze Zahl
    print(" 5: ", round(0.987))           #   "      "    "
    print(" 6: ", round(-0.987))          #   "      "    "
    print(" 7: ", round(1.23e2/1.1e2, 4)) # auf vier Nachkommastellen runden
    print(" 8: ", int(1.23e2/1.1e2))      # Nachkommastellen abschneiden, nächste, kleinere ganze Zahl
    print(" 9: ", int(0.987))             #       "             "
    print("10: ", int(-0.987))            #       "             "

    Der Typ complex –- Komplexe Zahlen

    Komplexe Zahlen bestehen aus einem Realteil und einem Imaginärteil. Der Imaginärteil 1 besteht aus einer reellen Zahl, die mit der imaginären Einheit i (der Wurzel aus -1) multipliziert wird. Zur Vermeidung von Missverständnissen benutzt Python für die imaginäre Einheit das j, um Probleme mit der Elektrotechnik zu vermeiden, wo das i bereits für den Strom vergeben ist und man daher dort ebenfalls j benutzt. Weiterhin muss das j nach der Zahl erscheinen. Komplexe Zahlen können können über die Standardfunktion complex() oder direkt definiert werden:

    c1 = 1 + 2j
    c2 = complex(1,2)
    c3 = -1.1e2 - 0.1e1j
    print(c1,c2,c3)
    

    Eine praktische Anwendung zeigt das folgende Beispiel, welches die Mandelbrotmenge in der seinerzeit von Benoit Mandelbrot erstellten Originalausgabe, die im reinen Textmodus erfolgte. Grafische Ausgaben waren nur auf den wenigsten Computern möglich. Man geht von der komplexen Gleichung $z_{n+1}=z_n^2+C$ aus, wobei $z_0=(0+i0)$ der Startwert ist und die komplexe Konstante C den Wert für die aktuellen Startkoordinaten enthält. Vorgegeben ist ein Koordinatensystem mit $-3<x<2.5$ und $-1.5<y<1.5$, welches in 24 Zeilen und 80 Spalten aufgeteilt wird. Wegen der reinen Textausgabe wird oben links begonnen (Zeile 1, Spalte 1, beziehungsweise $x=-3$ und $y=1.5$). Tendiert die Zahlenfolge $z_n$ gegen Null wird für das Koordinatenpaar(Spalte,Zeile) ein X ausgegeben, anderenfalls ein Leerzeichen. Abgebrochen wird die Iteration auch dann, wenn der Ortsvektor länger als rMax ist (aufgrund der Annahme, dass die Folge dann divergiert).

    MaxZeilen  = 24
    MaxSpalten = 80
    ReellMin   = -3.0
    ReellMax   = 2.5
    ImagMin    = -1.5
    ImagMax    = +1.5
    rMax       = 50
    MaxIter    = 26
    
    def iterat(x, y):     # (x|y) Startkoordinaten
      c = complex(x,y)    # Konstante
      k = 0               # Laufvariable
      z = complex(0,0)    # z_0 (startwert der Iteration)
      while (k < MaxIter) and (abs(z) <= rMax):
        z = z**2 + c
        k += 1            # um 1 inkrementieren
      return k
    
    DeltaReell = (ReellMax - ReellMin) / MaxSpalten # dx in Weltkoordinaten 
    DeltaImag = (ImagMax - ImagMin) / MaxZeilen     # dy in     "     "     }
    y = ImagMax
    while (y >= ImagMin):
      x = ReellMin
      while (x <= ReellMax):
          it = iterat(x,y)
          if (it >= MaxIter):
            print('X',end="")
          else:
            print(' ',end="")
          x = x + DeltaReell
      print()
      y = y - DeltaImag
    print()

    Interessierte können sich hier die Ausgabe als Grafik ansehen. Das entsprechende Python-Programm ist mandel.py.

    Für das Arbeiten mit komplexen Zahlen kann auch das Modul cmath aus der Standardbibliothek sinnvoll sein.

    Der Typ str –- Zeichenketten (Strings)

    Zeichenketten (Strings) sind eine Folge von beliebigen Zeichen, die wahlweise in 'einfachen' oder "doppelten" Anführungszeichen geschrieben werden. Hintergrundinformationen gibt es hier: https://kunststube.net/encoding/. Ein Computer versteht nur Bits (zwei Zustände). Für Zeichen wurden diese zu einem Byte zusammengefasst (8 Bit -- 256 Zustände). Durch die Internationalisierung (Japan hat alleine ca. 5000 Kanjis) reichte das irgendwann nicht, sodass Kombinationen von Bytes, wie UTF-16 (2 Byte) und UTF-32 (4 Byte) definiert wurden, um möglichst jedes Schriftzeichen, welches auf der Welt existiert, darstellen zu können.

    Nahezu jedes Python-Objekt kann durch die Standardfunktion str(object) in eine Zeichenkette gewandelt werden. Dies kann beispielsweise für eine eventuelle Ausgabe mit print() sinnvoll sein. Besteht eine Zeichenkette nur aus einem einzigen Zeichen, wird auch von einem char-Typ gesprochen.

    string_1 = "Eine Zeichenkette"
    string_2 = 'ドイツ'
    string_3 = "'Zeichen'"
    string_4 = '"Zeichen"'
    print(string_1, string_2, string_3, string_4)

    Der Rückgabewert von chr(Ganzzahl) ist

  • Ein Unicodezeichen korrespondierend zum Wert im Bereich von 0 bis 1,114,111, wobei nicht alle Zeichen darstellbar sind.
  • "ValueError", wenn das Argument außerhalb des zulässigen Bereichs ist.
  • "TypeError", wenn das Argument keine Zahl ist.

    Zeichenketten, die nur aus einem Zeichen bestehen, können auch durch ihre numerische Entsprechung dargestellt werden (Ordinalzahl):

    print(ord('@'))
    print(chr(64))
    z = ord('\\')#  Backslash maskieren!
    print(z)
    print(chr(z))
    print(chr(54321))

    print(chr(97))
    print(chr(65))
    print(chr(1200))
    x = "".join([chr(0x265a+n) for n in [2,4,3,1,0,3,4,2]])# Figuren
    print(x + "\n" + chr(0x265f)*8)                        # Bauern
    x = "".join([chr(0x2654+n) for n in [2,4,3,1,0,3,4,2]])# Figuren
    print(x + "\n" + chr(0x2659)*8)                        # Bauern
    print()
    print([chr(0x263f + n) for n in range(9)])# Planetensymbole

    Eine Zusammenstellung aller Zeichen mit ihren zugeordneten Zahlen in Hexadezimalform (Basis 16) findet man auf der Unicode-Seite https://www.unicode.org/charts/. Die Basiszeichen für lateinische Zeichen zeigt https://www.unicode.org/charts/PDF/U0000.pdf. Dem Zeichen @ ist demnach die Zahl 0040(16) zugeordnet, was der Dezimalzahl 4*16=64 entspricht. Die Schachfiguren und Planetensymbole findet man auf https://www.unicode.org/charts/PDF/U2600.pdf

    Zeichenketten können durch "Addition" miteinander kombiniert werden (concenation). Möchte man eine Zeichenkette beliebiger Länge in mehrfacher Wiederholung, so kann diese mittels * und einer ganzzahligen Zahl vervielfacht werden. Es ist etwas gewöhnungsbedürftig, dass die einfachen Rechenoperationen auch mit Strings möglich sind. Da Zeichenketten in Python unveränderbar sind, können auch nicht einzelne Zeichen ausgetauscht werden. Es muss in jedem Fall eine neue Zeichenkette erzeugt werden, die allerdings den alten Variablennamen erhalten darf.

    string_1 = "Eine Zeichenkette"
    string_2 = 'ドイツ'
    string_3 = "'Zeichen'"
    string_4 = '"Zeichen"'
    print(string_1 + 3*(string_2+" "))
    print(string_1+" "+string_3+" "+string_4)

    Die Länge (Anzahl Zeichen) einer Zeichenkette kann durch len() bestimmt werden:

    str_0 = "私の名前は「Herbert Voß」で、大学で働いています。"
    print("Der Satz hat ",len(str_0)," Zeichen!")

    Sollen Anführungszeichen, einfache oder doppelte, in einem String vorkommen, der durch gleichartige Anführungszeichen begrenzt ist, so muss das Zeichen durch einen vorangestellten Backslash maskiert (escaped) werden.

    str_0 = "\"Donald \""
    str_1 = '\'...\''
    print(str_0 + str_1 + " fehlt mir gerade noch.")

    Zur besseren Lesbarkeit von Programmen sollten Code-Zeilen nicht mehr als 80 Zeichen lang sein. Für die Zuweisung von längeren Zeichenketten kann mit einem Backslash am Ende einer Zeile erreicht werden, dass das folgende Zeilenendezeichen ignoriert wird und der BAckslash durch die folgende(n) Zeile(n) ersetzt wird, so dass der String-Variablen eine Zeichenkette ohne Zeilenumbruch zugewiesen wird:

    str_0 = 'Also sprach Zarathrusta: \
    „Es ist wahr: Wir lieben das Leben, nicht, weil wir ans Leben, sondern ans Lieben gewöhnt sind. \
    Es ist immer etwas Wahnsinn in der Liebe. Es ist aber auch immer etwas Vernunft im Wahnsinn.“'
    print(str_0)

    Hinter dem Backslash darf in derselben Zeile kein Kommentarzeichen folgen! Mehrzeilige Zeichenketten können alternativ auch in dreifache Anführungszeichen gesetzt werden. Diese sogenannten „Docstrings“ werden eigentlich verwendet, um längere Code-Abschnitte zu dokumentieren. Man kann sie aber auch für mehzeilge Strings verwenden, wobei das Zeilenendezeichen im Gegensatz zum obigen Beispiel erhalten bleibt und sich somit eine andere Ausgabe ergibt:

    str_0 = '''Also sprach Zarathrusta: 
    „Es ist wahr: Wir lieben das Leben, nicht, weil wir ans Leben, sondern ans Lieben gewöhnt sind. 
    Es ist immer etwas Wahnsinn in der Liebe. Es ist aber auch immer etwas Vernunft im Wahnsinn.“ '''
    print(str_0)

    Folgende Zeichenkombinationen haben eine Sonderbedeutung und unterliegen einer Sonderbehandlung:

    Zeichen Bedeutung
    \t Tabulator
    \n Newline (Zeilenumbruch)
    \r Carriage Return
    \\ Backslash
    \' Einfaches Anführungszeichen
    \" Doppeltes Anführungszeichen
    \xnn Sonderzeichen (ASCII ), repräsentiert durch eine zweistellige Hexadezimalzahl, beispielsweise \xe4
    \unnnn Sonderzeichen (16-bit-Unicode), repräsentiert durch eine vierstellige Hexadezimalzahl, beispielsweise \u7fe2

    Möchte man das Interpretieren der obigen Sonderzeichen unterbinden, kann dies durch ein vorangestelltes r („raw“) geschehen; beispielsweise r'a\tb' oder r"a\nb":

    str_0  =  'X\tY'
    str_r0 =  r'X\tY'
    str_1  =  "X\nY"
    str_r1 = r"X\nY"
    str_2  =  'X\rY'
    str_r2 = r'X\rY'
    str_3  =  'X\\Y'
    str_r3 = r'X\\Y'
    str_4  =  'X\'Y'
    str_r4 = r'X\'Y'
    str_5  =  'X\"Y'
    str_r5 = r'X\"Y'
    str_6  =  'X\xafY'
    str_r6 = r'X\xafY'
    str_7  =  'X\uafafY'
    str_r7 = r'X\uafafY'
    print(str_0, str_r0)
    print(str_1, str_r1)
    print(str_2, str_r2)
    print(str_3, str_r3)
    print(str_4, str_r4)
    print(str_5, str_r5)
    print(str_6, str_r6)
    print(str_7, str_r7)

    Indizierung von Zeichenketten

    Eine Zeichenkette entspricht einem Vektor, auf dessen einzelne Elemente (Zeichen) man mit dem Index-Operator [ ] zugreifen kann. Dabei beginnt die Zählung mit 0 und endet bei n Zeichen bei n-1. Zugriffe auf kleinere Werte als -n oder größere Werte als n-1 führt zu einem Fehler. Dabei ist zu beachten, dass mit dem Index[-1] das letzte Element und mit [-n] das erste Element gemeint ist:

    str0 = "Franz von Hahn"
    print("Element -1: "+str0[-1])
    n = len(str0)
    print("Element -n: "+str0[-n])

    str0 = "Hannah"
    print(str0)
    for i in range(len(str0)):  # 0,1,2,...,n-1
      print(i, str0[i])	
    print()
    for i in reversed(range(len(str0))): # n-1,n-2,...,2,1,0
      print(i, str0[i])
    print()
    for i in range(1,len(str0)+1):  # 0,1,2,...,n-1
      print(-i, str0[-i])
    print()

    Anstelle einzelner Zeichen kann auch eine Zeichenfolge (slice) aus der Zeichenkette extrahiert werden, wozu zwei durch Doppelpunkt getrennte Zahlen angegeben werden, die für den Bereich stehen. Der obere Bereich ist dabei jeweils nicht eingeschlossen. Fehlt die erste oder zweite Zahl, so wird jeweils vom Anfang, beziehungsweise Ende ausgegangen. Wird eine dritte, ebenfalls durch einen Doppelpunkt getrennt, angegeben, so kennzeichnet diese die Schrittweite. Bei einem negativen Wert kann von hinten gezählt werden:

    str0 = "Hannah"
    print(str0)
    for i in range(len(str0)):       # 0,1,2,...,n-1
      print(i, str0[i:], str0[:i])   # von i, bis i
    print()
    for i in range(0,len(str0)-1,2): # 0,2,4,.,n-1 mod 2
      print(i, str0[i:i+2])          # i,i+1
    print()
    str1 = "Ein längerer Satz, der sinnlos ist."
    print(str1[3:28:2])
    print(str1[28:3:-2])
    print()
    for i in range(len(str1)):       # 0,1,2,...,n-1
      print(i, str1[i::2], str1[:i:2])   # von i, bis i
    print()

    String-Funktionen

    Wie in allen Programmiersprachen gibt es auch in Python einige Funktionen, die im Allgemeinen in der Form Zeichenkette.Funktion() angewendet werden.

    Suchen von Teilstrings

    Mit dem in-Operator kann geprüft werden, ob eine Zeichenkette in einer anderen Zeichenkette enthalten ist, beziehungsweise wie oft. Für die Häufigkeit kann auch nur ein Intervall berücksichtigt werden:

    str0 = "Hannah Montana"
    if 'an' in str0:
      print('"an" ist in "'+str0+"\" enthalten")
    else:
      print('"an" ist in "'+str0+"\" nicht enthalten")
    
    n = str0.count('an')
    print('"an" ist in "'+str0+"\" genau "+str(n)+"-mal enthalten")
    
    n = str0.count('an',5,13)
    print('"an" ist in "'+str0[5:13]+"\" genau "+str(n)+"-mal enthalten")

    Mit str.find() kann die Position eines Teilstrings innerhalb eines Stringvektors bestimmt werden. Ist der Teilstring nicht enthalten, so wird -1 zurückgegeben. Zu beachten ist, dass die Zählung mit Null beginnt. Mit str.rfind() kann man die Suche von rechts beginnen lassen. Durch weitere Paremeter kann die Suche wieder auf Teilintervalle beschränt werden:

    str0 = "Hannah Montana"
    n = str0.find('an')
    if n > -1: 
      print('"an" ist in "'+str0+"\" erstmalig an der Stelle ",n)
    else:
      print('"an" ist in "'+str0+"\" nicht enthalten")
    
    n = str0.rfind('an')
    if n > -1: 
      print('"an" ist in "'+str0+"\" letztmalig an der Stelle ",n)
    else:
      print('"an" ist in "'+str0+"\" nicht enthalten")
    
    n = str0.find('an',10,20)
    if n > -1: 
      print('"an" ist in "'+str0+"[10:20]\" erstmalig an der Stelle ",n)
    else:
      print('"an" ist in "'+str0+"[10:20]\" nicht enthalten")

    Interessiert grundsätzlich nur das Ende Strings, beispielsweise bei einem Dateinamen, so kann die Funktion str.endswith() genutzt werden, welche einen Boolschen Wert zurückliefert. Analog dazu existiert auch eine Funktion str.startswith():

    str0 = "index.html"
    if str0.endswith('.html'): 
      print(str0, "ist eine html-Datei")
    else:
      print(str0, "ist keine html-Datei")
    
    if str0.endswith('.php'): 
      print(str0, "ist eine php-Datei")
    else:
      print(str0, "ist keine php-Datei")
    
    if str0.startswith('index'): 
      print(str0, "ist die standardmäßige index-Datei")
    else:
      print(str0, "ist keine index-Datei")
    Ersetzen von Teilstrings

    Wie bereits erwähnt wurde, sind einmal definierte Zeichenketten unveränderbar. Daher kann der Index-Operator nicht auf der linken Seite einer Zuweisung (Gleichheitszeichen) stehen. Es muss daher ein Zwischenschritt erfolgen, was von der Funktion str.replace() intern erledigt wird:

    str0 = "Hannah Montana"
    print(str0.replace("Hannah","Hanna"))
    str0 = str0.replace("Hannah","Johanna")
    print(str0)
    str1 = "Hannah Montana".replace("Montana","Idaho")
    print(str1)

    Komfortablere und vor allem komplexere Ersetzungen sind mit Hilfe von regulären Ausdrücken möglich. Man kann auch mit Übersetzungstabellen arbeiten:

    str0 = "H%(&=annah)"
    sonderzeichenB = "-=[]()"  # 
    trans_table = str0.maketrans(sonderzeichenB, " " * len(sonderzeichenB))
    print(trans_table) # dictionary a->b (a wird b)
    print()
    str0 = str0.translate(trans_table)
    print(str0)
    Groß- und Kleinschreibung ändern

    Da Groß-/Kleinschreibung für Python signifikant ist, kann die Bedeutung von Zeichenketten nur dann verglichen werden, wenn sie vorher in KLein- oder Großbuchstaben gewandelt werden. Mit str.capitalize() werden sie in die Standardschreibweise mit einem großen Anfangsbuchtsaben und Rest Kleinbuchstaben gewandelt, wohingegen str.title() dies für jedes Teilwort einer Zeichenkette macht. Groß- und Kleinbuchstaben können durch str.swapcase() vertauscht werden:

    str0 = "Hannah"
    str1 = "hANNah"
    str2 = "ANNah"
    if str0.lower() == str1.lower():
      print("Die Zeichenketten str0 und str1 bedeuten dasselbe!")
    if str0.upper() == str1.upper():
      print("Die Zeichenketten str0 und str1 bedeuten dasselbe!")
    
    if str0.upper() == str2.upper():
      print("Die Zeichenketten str0 und str2 bedeuten dasselbe!")
    else:
      print("Die Zeichenketten str0 und str2 bedeuten nicht dasselbe!")
    
    str3 = str0+" "+str1+" "+str2 
    print(str3)
    print(str3.capitalize())
    print(str3.title())
    print(str3.swapcase())
    Leerzeichen am Anfang und Ende entfernen

    Mit den Funktionen str.lstrip(), str.rstrip() und str.strip() lassen sich Leerzeichen am Anfang, am Ende oder an beiden Stellen einer Zeichenkette entfernen;

    str0 = "        Johnny Mauser        "
    print("|"+str0.lstrip()+"|")
    print("|"+str0.rstrip()+"|")
    print("|"+str0.strip()+"|")
    Text zentrieren

    Die Funktion str.center() zum Zentrieren einer Zeichenkette innerhalb einer vorgegebenen Stringlänge ist faktisch nur für eine folgende Ausgabe sinnvoll.

    str0 = "Johnny Mauser"
    print("|"+str0.center(10)+"|") # keine Zentrierung, da Zeichenzahl größer als 10!
    print("|"+str0.center(20)+"|")
    print("|"+str0.center(30)+"|")
    print("|"+str0.center(40)+"|")
    Aufteilen und Zusammenfügen von Zeichenketten

    Mit der Funktion str.split() kann eine Zeichenkette in eine Liste von Teilstrings aufgeteilt werden, um beispielsweise festzustellen, wieviel Wörter ein Text enthält. Standardmäßig wird das Leerzeichen als Trennzeichen benutzt, es kann über den optionalen Parameter aber jedes andere Zeichen angegeben werden. Die Umkehrung erfolgt mit separator.join(), wobei der Separator eine beliebige Zeichenkette sein kann, die als Trennzeichen zwischen den zusammenzuführenden Elementen benutzt wird.

    str0 = """Eine wunderbare Heiterkeit hat meine ganze Seele eingenommen, gleich den süßen Frühlingsmorgen, 
    die ich mit ganzem Herzen genieße. Ich bin allein und freue mich meines Lebens in dieser Gegend, die für solche Seelen geschaffen 
    ist wie die meine. Ich bin so glücklich, mein Bester, so ganz in dem Gefühle von ruhigem Dasein versunken, daß meine Kunst 
    darunter leidet. Ich könnte jetzt nicht zeichnen, nicht einen Strich, und bin nie ein größerer Maler gewesen als in diesen 
    Augenblicken. Wenn das liebe Tal um mich dampft, und die hohe Sonne an der Oberfläche der undurchdringlichen Finsternis meines 
    Waldes ruht, und nur einzelne Strahlen sich in das innere Heiligtum stehlen, ich dann im hohen Grase am fallenden Bache liege, 
    und näher an der Erde tausend mannigfaltige Gräschen mir merkwürdig werden; wenn ich das Wimmeln der kleinen Welt zwischen 
    Halmen, die unzähligen, unergründlichen Gestalten der Würmchen, der Mückchen näher an meinem Herzen fühle, und fühle die 
    Gegenwart des Allmächtigen, der uns nach seinem Bilde schuf, das Wehen des Alliebenden, der uns in ewiger Wonne schwebend 
    trägt und erhält; mein Freund! Wenn's dann um meine Augen dämmert, und die Welt um mich her und der Himmel ganz in meiner 
    Seele ruhn wie die Gestalt einer ... """
    Woerter = str0.split()
    print(Woerter)
    print("Der Text hat insgesamt ", len(Woerter)-1, " Worter") # -1 wegen ...  :-)
    
    print(''.join(Woerter))   # Kein Trenner angegeben
    print(' '.join(Woerter))  # Leerzeichen als Trenner
    
    Vektor = "1, 2, 3, 4, 5, 1.234, 1.33e17, 0.12"  # komma-separierte Liste
    strVektor = Vektor.split(",")
    print(strVektor)
    print("Der Vektor hat ",len(strVektor)," Elemente")
    str1 = ""
    print(str1.join(strVektor))
    print(", ".join(strVektor))
    Formatierung von Zeichenketten

    Bei der formatierten Ausgabe von Strings und Zahlenwerten, die bezogen auf die Ausgabe ebenfalls Zeichenketten darstellen, kann man eine Notation in Anlehnung an die Programmiersprache C benutzen. Die sogenannten Platzhalter werden durch ein Prozentzeichen markiert. Alternativ kann die Python-Funktion string.format() benutzt werden, bei der die Platzhalter durch ein Paar von geschweiften Klammern festgelegt werden. Dabei gilt die Notation PlatzhalterNr:Formatierung.

    import math  # math Modul laden
    print('Der Wert von e ist %s und der von pi ist %s' % (math.e,math.pi))
    
    print('Der Wert von e ist {} und der von pi ist {}'.format(math.e,math.pi))
    
    print('Der Wert von e ist {:5.4f} und der von pi ist {:8.3f}'.format(math.e,math.pi))
    
    print('Der Wert von e ist {1:5.4f} und der von pi ist {0:8.3f}'.format(math.e,math.pi))

    Eine Liste aller Formattypen gibt es auf dieser Seite.

    Formatierung von Zeichenketten mit f-Strings

    Python hat ab Version 3.6 die sogenannten f-strings (formatted string literals) eingeführt, was zu einfacherem und lesbarerem Code führt.

    print(f"2 + 3 is equal to {2+3}")
    variable = 'alignment!'
    print(f'foo {variable:>20} bar')
    print(f'foo {variable:<20} bar')
    print(f'foo {variable:^20} bar')

    Die allgemeine Syntax ist: variable:{alignment}{width}

    Eine etwas anspruchsvollere Ausgabe ergibt sich für die DataFrames des Pandas Moduls:

    import pandas as pd
    df = pd.DataFrame.from_dict({'Value' :[234534.43, 987324543.34, 1234345.34, 8234.43]})
    df['Currency'] = [f'${x:,.2f}' for x in df['Value']]
    df['Currency 2'] = df['Value'].apply(lambda x: f'${x:,.2f}')
    print(df)

    print("\nPyramide 1:")
    maxN = 11
    for i in range(maxN):
      x = "* " * i            # Zeichenkette "* " i-mal wiederholen
      print(f'{x:^{maxN*2}}') # Zentriert auf 22 Zeichen ausgeben
    #           ^^^

    print("\nPyramide 2:")
    maxN = 11
    for i in range(maxN):
      x = "* " * (maxN-i)     # Zeichenketter (11-i)-mal wiederholen
      print(f'{x:^{maxN*2}}') # Wie 1 nur umgekehrte Reihenfolge
    #           ^^^

    print("\nPyramide 3:")
    maxN = 11
    for i in range(maxN):
      x = '* ' * i # Wie 1
      print(f'{x:<{maxN*2}}')#  Wie 1, nur linksbündig
    #           ^^^

    print("\nPyramide 4:")
    maxN = 11
    for i in range(maxN):
      x = '* ' * i  # Wie 1
      print(f'{x:>{maxN*2}}')#  Wie 1, nur rechtsbündig
    #           ^^^

    Liste aller Stringfunktionen

    Eine vollständige Liste an String-Funktionen erhält man, indem man die Funktion dir() auf einen beliebigen String anwendet, wobei allerdings auch die internen Funktionen angegeben werden. Eine vollständige Liste der Benutuzerfunktionen für Zeichenketten gibt es auf dieser Seite.

    Listen und Tupel

    Listen und Tupel sind faktisch Vektoren oder Matrizen, die eine Sequenz von Objekten beliebigen Datentyps als Liste speichern. Jedes Element einer Liste kann dabei von einem anderen Typ sein. Eine Liste wird in eckige Klammern gesetzt und ein Tupel in runde Klammern. Ein Tupel ist grundsätzlich wie eine Zeichenkette, nachdem sie definiert wurde, nicht mehr veränderlich. Sie bietet sich daher immer dann an, wenn man Anwender vor der unbeabsichtigten Modifikation einer Liste schützen will. Es handelt sich bei einer Liste und einem Tupel jeweils um kommaseparierte Folgen, die über die Funktionen gleichen Names in den jeweils anderen Typ gewandelt werden können.

    liste0 = ['a', 'b', 'c', 1, 2, 3.14, True]
    tupel0 = ('a', 'b', 'c', 1, 2, 3.14, True)
    
    liste1 = list(('a', 'b', 'c', 1, 2, 3.14, True))  # Tupel in Liste wandeln
    print(liste0,liste1)
    if 3.14 in liste1:
      print("3.14 ist in der Liste")
    tupel1 = tuple(['a', 'b', 'c', 1, 2, 3.14, True]) # Liste in Tupel wandeln
    print(tupel0,tupel1)
    if True in tupel1:
      print("True ist in dem Tupel")
    print("liste0 hat ",len(liste0)," Elemente.")
    print("tupel0 hat ",len(tupel0)," Elemente.")
    

    Indizierung von Listen und Tupeln

    Der Zugriff auf die einzelnen Elemente erfolgt wie bei Zeichenketten, die letztlich nicht anderes als ein Tupel sind.

    liste0 = ['a', 'b', 'c', 1, 2, 3.14, True]
    tupel0 = ('a', 'b', 'c', 1, 2, 3.14, True)
    print(liste0[0],tupel0[0])    # Erstes Element der Liste/Tupel
    print(liste0[5],tupel0[5])    # Sechstes Element der Liste/Tupel
    print(liste0[-2],tupel0[-2])  # Vorletztes Element der Liste/Tupel
    print(liste0[3:5],tupel0[3:5])# 4. und 5. Element
    print(liste0[3:],tupel0[3:])  # ab 4. Element
    print(liste0[:5],tupel0[:5])  # bis 5. Element
    print(liste0[1:5:2],tupel0[1:5:2])  # 2-er Schrittweite

    # a[start:stop:step], default step is 1
    a = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
    print(a)
    b = a[1:3] # Note that the last index is not included
    print("1: ",b)
    b = a[2:] # until the end
    print("2: ",b)
    b = a[:3] # from beginning
    print("3: ",b)
    a[0:3] = [0] # replace sub-parts, you need an iterable here
    print("4: ",a)
    b = a[::2] # start to end with every second item
    print("5: ",b)
    a = a[::-1] # reverse the list with a negative step:
    print("6: ",a)
    b = a[:] # copy a list with slicing
    c = a    # only a reference
    print("7: ",a,b,c)
    a.pop(0)
    print("8:, ",a,b,c)

    Die Erweiterung von Tupeln ist möglich, jedoch in der Handhabung etwas gewöhnungsbedürftig, denn Tupel können nur dann erweitert werden, wenn das anzuhängende Tupel bei der Definition ein abschließendes Komma aufweist, wenn es nur aus einem Element besteht. Hat es mehr Elemente, so kann das Komma entfallen. Dabei spielt es keine Rolle, ob zu erweiternde Tupel selbst mit einem Komma endet, wie beispielsweise das erste tupel1 im folgenden Beispiel:

    tupel0 = ('a', 'b', 'c', 1, 2, 3.14, True)   # kein Komma am Ende
    tupel1 = ('a', 'b', 'c', 1, 2, 3.14, True, ) # mit Komma am Ende
    print("0: ", tupel0)
    print("1: ", tupel1)
    t_Add = (False, "foo", )   #
    #t_Add = (False)           # ergibt einen Fehler! (Ausprobieren)
    tupel0 = tupel0 + t_Add    # ok
    tupel1 = tupel1 + t_Add    # ok
    print("0: ", tupel0)
    print("1: ", tupel1)
    t_Add = (1,2,)
    tupel0 = tupel0 + t_Add 
    tupel1 = tupel1 + t_Add 
    print("0: ", tupel0)
    print("1: ", tupel1)
    t_Add = ("bar", "baz" )    # ok, obwohl hinten kein Komma!
    tupel0 = tupel0 + t_Add 
    tupel1 = tupel1 + t_Add 
    print("0: ", tupel0)
    print("1: ", tupel1)

    Mehrdimensionale Listen

    Eine Matrix besteht bekanntermaßen aus einzelnen Vektoren, was sich auch auf Listen übertragen lässt. Eine Liste, bei der jedes Element wiederum eine Liste ist (Verschachtelung), usw., wird als mehrdimensionale Liste bezeichnet. Auf diese können die gleichen Funktionen angewendet werden, wie für eine eindimensionale Liste. Für jede Dimension wird beim Zugriff ein paar an eckigen Klammern angegeben, sodass bei einer zweidimensionalen MAtrix bei zwei eckigen Klammern genau ein Element das Ergebnis ist. Es lassen sich auch hier BEreiche auswählen..

    liste0 = [ ['a', 'b', 'c'], [ 'd', 'e', 'f'], [ 'g', 'h', 'i']]
    print("1: ",liste0)
    print("2: ",liste0[0])
    print("3: ",liste0[1][2])
    print("4: ",liste0[2][1])
    print("5: ",liste0[:2][1:])
    print("6: ",liste0[:1][2:])

    Listen-Funktionen

    Für Listen existieren Funktionen, die in der Form liste.funktionsname() angewendet werden können.

    Listen verknüpfen

    Durch liste_1.extend(liste_2) kann liste_2 an liste_1 angehängt werden. Dabei ist zu beachten, dass liste_1 nach dem Aufruf um liste_2 erweitert ist, das Rückgabeergebnis der Funktion aber nur None ist. Listen können auch durch einfache Addition oder Multiplikation verkettet werden. Zu beachten ist, dass die neue Liste nur um die Elemente erweitert wird. Im Gegensatz dazu kann mit lste.append() die komplette Liste als eigenständiges Element angehängt werden.

    liste0 = [ ['a', 'b', 'c'], [ 'd', 'e', 'f'], [ 'g', 'h', 'i'] ]
    liste1 = [ [ 0, 1, 2 ], [ 3, 4, 5 ], [ 6, 7, 8 ] ]
    print(liste0.extend(liste1))
    print(liste0)
    print(liste1)
    print()
    liste2 = liste0 + liste1
    print(liste2)
    liste3 = 2 * liste1
    print(liste3)
    print()
    liste0 = [1, 2, 3]
    liste1 = ['a', 'b', 'c' ]
    liste4 = liste0.append(liste1)
    print(liste4, liste0)
    Listen sortieren
    Mit der Funktion liste.sort() können die Elemente einer Liste in aufsteigender und mit list.reverse() in absteigender Reihenfolge sortiert werden. Der Rückgabewert der Funktionen ist jeweils None, d.h. es wird keine neue Liste erstellt, sondern die bestehende bearbeitet.
    liste0 = [3, 1, -5, 8, 2]
    liste1 = liste0.sort()
    print(liste0, liste1)
    liste2 = liste0.reverse()
    print(liste0, liste2)

    Neben der Funktion sort() existiert eine weitere Variante, die jedoch die Liste selbst _nicht_ sortiert, sondern nur die sortierte Liste zurückgibt. Vergleiche:

    nums = [2, 3, 1, 5, 6, 4, 0]
    print("Anwendung von sort() wie oben:")
    print(nums.sort())    # None  
    print(nums)           # [0, 1, 2, 3, 4, 5, 6]
    
    print("\nAnwendung von sorted():")
    nums = [2, 3, 1, 5, 6, 4, 0] #    
    print(sorted(nums))          # [0, 1, 2, 3, 4, 5, 6]  sortierte Liste
    print(nums)                  # [2, 3, 1, 5, 6, 4, 0]  alte unsortierte Liste

    list.sort() sollte immer dann verwendet werden, wenn eine dauerhafte Veränderung der Liste beabsichtigt ist und die Wiederherstellung der ursprünglichen Reihenfolge der Elemente nicht erwünscht ist. Anderenfalls sollte sorted() verwendet werden, wenn das zu sortierende Objekt iterierbar ist (z. B. Liste, Tupel, Wörterbuch, String) und das gewünschte Ergebnis eine sortierte Liste ist, die alle Elemente enthält.

    Eine eingehende Beschreibung der verschiedenen Möglichkeiten findet man in sorting.html und speziell für dictionaries in sorting_dicts.html.

    Elemente indizieren, einfügen und entfernen

    Das Zählen und Suchen bestimmter Elemente in einer Liste erfolgt analog zu Zeichenketten:

    liste0 = [ ['a', 'b', 'c'], [ 'd', 'e', 'f'], [ 'g', 'h', 'i']]
    liste1 = 2 * liste0
    print("liste1: ",liste1)
    print("Es gibt ",liste1.count('a'), " 'a' in der Liste.") 
    print("Es gibt ",liste1.count(['d','e','f']), " ['d','e','f'] in der Liste.") 
    if ['e','f'] in liste1:
      print("['e','f']“ in liste1 gefunden")
    else:
      print("['e','f'] nicht in liste1 gefunden")
    if ['d','e','f'] in liste1:
      print("['d','e','f']“ in liste1 als ", liste1.index(['d','e','f'])+1,". Element gefunden!",sep="")# kein Zwischenraum
    else:
      print("['d','e','f']“ nicht in liste1 gefunden")

    as Einfügen von Elementen in eine Liste (nicht Tupel!) erfolgt mit liste.insert(indexnummer, element) und das Entfernen mit liste.remove(element), beziehungsweise liste.pop(indexnummer):

    liste1 = [ ['a', 'b', 'c'], [ 'd', 'e', 'f'], [ 'g', 'h', 'i']]
    print("liste1: ",liste1)
    
    liste1.insert(0,"Johnny")
    liste1.insert(-1,"Mauser")
    print(liste1)
    
    liste1.remove("Mauser")
    print(liste1)
    
    liste2 = liste1.pop(0)  # 1. Element entfernen
    print("liste1: ",liste1, "liste2: ",liste2)
    
    liste2 = liste1.pop()   # Letztes Element entfernen
    print("liste1: ",liste1, "liste2: ",liste2)

    Die Funktion liste.pop(indexnummer) liefert das gelöscht Element zurück. Eine bestimmten Bereich einer Liste oder komplett löschen lässt sich mit del liste[] erreichen. Sollen nur die Elemente, aber nicht die Liste an sich gelöscht werden, so lässt sich das mit liste.clear() erreichen.

    liste1 = [ ['a', 'b', 'c'], [ 'd', 'e', 'f'], [ 'g', 'h', 'i']]
    print("liste1: ",liste1)
    print(liste1.pop()) #  letztes Element löschen
    print(liste1)
    
    liste2 = 4 * liste1
    print(liste2)
    
    del liste2[3:6]# Löschen der Elemente 3, 4, 5 
    print(liste2) 
    
    liste2.clear() # Listenelemente löschen, Liste bleibt definiert   
    print(liste2)

    Listen kopieren
    Die Anweisung liste1 = liste0 ist keine echte Kopie der Liste, sondern nur eine Kopie des Namens. Die neue Liste zeigt auf dieselben Elemente wie die alte Liste. Von dieser ein Element gelöscht, so fehlt es auch in der "Kopie". Eebenso ergibt eine Veränderung von liste1 die gleiche Veränderung in liste0. Bei einer echten Kopie mit liste.copy() passiert das nicht; es existieren dann zwei unabhängige Listen.:

    liste0 = [ ['a', 'b', 'c'], [ 'd', 'e', 'f'], [ 'g', 'h', 'i']]
    liste1 = liste0
    print("liste0: ",liste0) 
    print("liste1: ",liste1)
    
    print(liste0.pop())             # letztes Element von liste0 löschen und anzeigen
    liste1[1] = [ "Johnny Mauser" ] # 2. Element in liste1 neu definieren
    
    print("liste0: ",liste0)        # ebenfalls mit "Johnny Mauser" 
    print("liste1: ",liste1)        # ebenfalls ohne letztes Element
    
    liste2 = liste0.copy()          # erzeuigen einer echten Kopie 
    liste2.append([ "Franz von Hahn" ])   # an liste2 anhängen
    print("liste0: ",liste0)        # ohne "Franz von Hahn" 
    print("liste2: ",liste2)        # mit "Franz von Hahn"

    Visuelle Zusammenfassung der Listenoperationen

    Alle Funktionen gibt es auch hier https://docs.python.org/3/tutorial/datastructures.html erklärt!

    List-Comprehensions

    Dies ist eine vereinfachte Methode, um eine Liste mit Elementen automatisiert zu füllen:

    from math import *  # alles importieren
    l1 = [i for i in range(5)]
    print(l1)
    l2 = [sqr(i) for i in range(5)]
    print(l2)

    Die Fibonacci-Zahlenreihe ergibt sich durch Addition der zwei vorhergehenden Elemente: 1 1 2 3 5 8 ...

    f1 = 0
    f2 = 1
    fib = []
    for i in range(0, 10):
      fib. append(f1)
      temp = f1+f2
      f1 = f2
      f2 = temp
    print(fib)

    Durch Komprimierung der Schleife lässt sich das vereinfachen.

    fib = [0,1]
    [fib.append(fib[-2]+fib[-1]) for i in range(8)]
    print(fib)

    Gegeben sei eine Liste der ersten 100 natürlichen Zahlen ohne Null durch nat100 = range(1,101) Es soll eine neue Liste der Primzahlen bis 100 erstellt werden. Dazu kann man über die einzelnen Elemente der Liste iterieren, der sogenannten List-Comprehension. Durch definierte Filter kann die neue Liste an Bedingungen geknüpft werden. Im folgenden Beispiel kommt die natürliche Zahl n nur dann in die Liste, wenn es eine Primzahl ist.

    import math # für math.sqrt (Wurzel)
    def is_prime(n):   # Überprüfe n
        return not any(n % p == 0 for p in range(2, int(math.sqrt(n)) + 1)) # p Laufvariable 
        # any() gibt true zurück wenn mindestens einmal eine Division ohne Rest möglich ist
        # not any() ist dann true, wenn keine Division ohne Rest möglich ist -> Primzahl
    
    nliste = range(1,101)
    prim_liste = [ i for i in nliste if is_prime(i) ] # i nur dann in die Liste, wenn Primzahl
    print(prim_liste)
    print("Insgesamt ", len(prim_liste), " Primzahlen.", sep="")

    Für any und all siehe auch all_any.html

    Es ist auch möglich, Elemente aus zwei Listen an Bedingungen zu knüpfen und dann in eine Liste zu setzen.

    import random
    liste0 = [random.randint(1,51) for i in range(50)] # Zufallszahlen 1..50
    liste1 = [random.randint(1,51) for i in range(50)] #     "
    print(liste0) # zufällig verteilte Liste
    print(liste1) #    "        "        "
    print()
    
    liste2 = [ i for i in liste0 if i in liste1 ] # i nur dann in die Liste, wenn in liste0 und 1
    liste0.sort() # sortierte Liste 
    liste1.sort() #     "       "
    print(liste0)
    print(liste1)
    print()
    
    liste2.sort()
    print(liste2)
    print("Insgesamt ", len(liste2), " gemeinsame Zahlen.", sep="")
    print()
    
    liste3 = []
    for i in range(len(liste2)):
      if liste2[i] not in liste3:   # nur in liste3 hinzufügen, wenn nicht schon vorhanden
        liste3.append(liste2[i])
    print(liste3)
    print("Insgesamt ", len(liste3), " echte gemeinsame Zahlen.", sep="")

    Ebenso können bei gleich langen Listen alle Elemente beispielsweise dividieren. Der Zugriff erfolgt dann über die Laufvariable.

    liste_1 = [1, 2, 3, 4, 8]
    liste_2 = [2, 30, 4, 15, 6]
    liste_div = [liste_1[i] / liste_2[i] for i in range(len(liste_1))]
    print(liste_div)

    Listen-Destrukturierung ("packing und unpacking")

    In Zuweisungen kann der Inhalt eienr iterierbaren Liste einzelnen VAriablen zugeordent werden, was auch als "unpacking" bezeichnet wird:

    a, b = ( 1, 2 )
    print (a,b)

    Hierbei muss der Anwender selbst sicherstellen, dass die Liste mindestens so viele Variablen enthält wie zugewiesen werden sollen. Anderenfalls gibt es eine Fehlermeldung. Eine Liste unbekannter Länge kann über eine spezielle Syntax "entpackt" werden, wobei head ein Skalar und tail eine Liste ist:

    head, *tail = [ 1, 2, 3, "a", 5 ]
    print (head, tail)
    L_0 = [1, 2, 3, "a",5 ] 
    head = L_0[0]      # Alternative
    tail = L_0[1: ]
    print(head, tail)

    Diese Syntax kann auch auf mehrere Zuweisungen ausgedehnt werden, die jeweils alle Werte bis zum Ende der Liste beachten. Im folgenden Bespsiel bekommt b den zweiten und z den letzten Wert zugewiesen, sodass other alle verbleibenden Werte als Liste zugeordnet werden:

    a, b, *other, z = [1, 2, 3, "a", 5 ] 
    print (a, b, other, z, sep="; ")

    Ist man nur an bestimmten Werten der Liste interessiert, so können einzelne Elemente mit dem Operator _ ignoriert werden, wobei zu beachten ist, dass dieser OPerator letztlich wie eine Variable funktioniert.

    a, _ = [ 1 , 2 ]
    print (a)
    a, _, c = ( 1 , 2 , 3 ) 
    print (a, c)
    
    a, b, *_ = [ 1, 2, 3, "a", 5 ]    # Nur Python Version > 3.0
    print (a, b)
    
    a, *_, b = [ 1, 2, 3, "a", 5 ] 
    print (a, b)
    
    a, _, b, _, c, *_ = [ 1, 2, 3, "a", 5, "b" ] 
    print (a, b, c)

    Gleiches Verhalten kann man auch mit Funktionen und deren Parameter erreichen. Normalerweise muss eine Funktion alle Parameter definieren, die im Funktionskörper benutzt werden:

    def func_1(arg1 , arg2 , arg3):
      return (arg1 , arg2 , arg3)
    func_1( 1, 2, 3 )

    Alternativ war auch die Anwendung des key-value-Systems möglich, was unterschiedliche Aufrufe zulässt:

    Übergibt man mit dem *-Operator eine Liste, so wird diese automatisch entpackt und als einzelne Parameter verwendet:

    L_0 = [ 1, 2, 3 ]
    def func_3(arg1, arg2, arg3): 
      return (arg1 , arg2 , arg3)
    print(func_3( *L_0))
    print(func_3(*['w', 't', 'f']))

    Auch hier muss die Zahl der Elemente der Liste der Zahl der erwarteten Parameter der aufgerufenen Funktion entsprechen. Anderenfalls gibt es eine Fehlermeldung.

    Der Doppelsternoperator kann genutzt werden, wenn statt der Liste ein Dictionary mit den entsprechenden Parameterbezeichnungen übergeben wird.

    d_0 = { 'arg1' : 1, 'arg2' : 2, 'arg3' : 3 }
    def func_3(arg1, arg2, arg3): 
      return (arg1, arg2, arg3)
    def func_4(arg1="a", arg2="b", arg3="c"): 
      return (arg1, arg2, arg3)
    print(func_3( **d_0))
    print(func_3(*['w', 't', 'f']))
    print()
    
    print(func_4( *[1]))
    print(func_4( **{'arg2': 2}))
    print()
    
    def func_5(arg1, arg2="b", arg3="c"): 
      return (arg1, arg2, arg3)
    print(func_5( *[1]))
    print(func_5( *[1, 2, 3]))
    print(func_5( **{'arg1': 1}))
    print(func_5( *[1, 2], **{'arg3': 3}))

    Die Definition einer Funktion ohne genaue Kenntnis über die Zahl und Position der übergebenen Parameter ist ebenfalls mit den Stern-Operatoren möglich:

    def func_1(*args , **kwargs):   # *args and **kwargs are special parameters that are set to a tuple and a dict
        print(args, kwargs) 
    
    # ignoriert den Rückgabewert "None" (wird _ zugeordnet)
    _ = func_1(1, 2, 3)                         # tuple, empty dict
    _ = func_1(a=1, b=2, c=3)                   # empty tuple and dict
    _ = func_1('x', 'y', 'z', a=1, b=2, c=3)    # tuple and dict

    Die Sternvarianten werden sehr häufig benutzt, um nicht festgelegte PArametersequnzen an FUnktionen zu übertragen. Im Folgenden ein BEispiel bei dem die String-Klasse erweitert wird:

    class A:                                                     # Basisklasse
      def __init__(self, *args, a, **kwargs):                    # beliebige Argumente, kw a, beliebige keywords
        print("A", *args, a, dict(**kwargs), sep="; ")
    
    class B(A):
      def __init__(self, arg1, *args, b, **kwargs):              # arg1, beliebige Argumente, kw b, beliebige keywords
        print("B vorher", arg1, b, *args, dict(**kwargs), sep="; ")
        super(B, self).__init__(*args, **kwargs)                 # A aufrufen und "erben"
        print("B nachher", arg1, b, *args, dict(**kwargs), sep="; ")
    
    class A1(A):
      def __init__(self, arg1, *args, a1, **kwargs):             # arg1, beliebige Argumente, kw a1, beliebige keywords
        print("A1 vorher", arg1, a1, *args, dict(**kwargs), sep="; ")
        super(A1, self).__init__(*args, **kwargs)                # A aufrufen und "erben"
        print("A1 nachher", arg1, a1, *args, dict(**kwargs), sep="; ")
    
    class B1(A1, B):
      def __init__(self, arg1, *args, b1, **kwargs):             # arg1, beliebige Argumente, kw b1, beliebige keywords
        print("B1 vorher", arg1, b1, *args, dict(**kwargs), sep="; ")
        super(B1, self).__init__(*args, **kwargs)                # Erst A1, dann B aufrufen und "erben"
        print("B1 nachher", arg1, b1, *args, dict(**kwargs), sep="; ")
    
    B1(1, 2, 3, a1=6, b1=5, b="hello", a=None)

    Tipps und Tricks

    Named Tuple

    Rückgabe eines Tuples mit Zugriff durch Namen auf die einzelnen Elemente:

    from collections import namedtuple
    
    def multiple_values():
      MyTuple = namedtuple("MyTuple", ["name", "age", "car"]) # Name, [Elemente]
      name = "Mark"
      age = 21
      car = "Ford"
      return MyTuple (name, age, car)
    
    # Calling the function
    result = multiple_values()
    name = result.name
    age = result.age
    car = result.car
    print(f"Name: {name}, Age: {age}, Car: {car}")
    Elemente von beiden Seite einer Liste löschen (pop)

    Wenn man Elemente an beiden Seiten einer Liste hinzufügen oder entfernen möchte, so kann man deque (double-ended queue) verwenden. Anders als bei einer normalen Liste, bei der man Elemente nur am Ende hinzufügen oder entfernen kann, kann dies mit deque an beiden Seiten erfolgen

    from collections import deque
    
    my_list = deque([1, 3])
    # appending on the left end of the list
    my_list.appendleft(5)
    
    # appending on the right end of the list
    mylist.append (7)#  right is the default
    print(my_list)
    print()
    my_list = deque([1, 3, 9, 6])
    
    # pop element on the left end of the list
    my_list.popleft # pops 1
    # pop element on the right end of the list
    my_list.pop() # pops 6
    print(my_list)

    Mengen mit set() und frozenset

    Ein Set (eine Menge) bezeichnet in Python eine Sammlung an Objekten beliebigen Datentyps, wobei jedes Objekt nur ein einziges Mal in der Menge enthalten sein darf. Sets werden in Python in geschweifte Klammern gesetzt: Durch Anwendung von Operatoren auf paarweise je zwei Sets können nach den allgemein bekannten Regeln der Mengenlehre neue Sets gebildet werden. Da Sets ein Element nur jeweils einmal enthalten können, können mit set() aus einer Liste doppelte Einträge entfernt werden.

    set_1 = { 'a', 'b', 'c', 1, 2, 3 }          
    set_2 = set( [ 'a', 'b', 'c', 1, 2, 2, 3, 3 ] ) # doppelte Einträge werden entsorgt
    liste_2 = list(set_2)
    set_3 = { 'b', 'c', 'd', 2, 3, 4 }
    print(set_1)
    print(set_2, liste_2)
    print(set_3)
    
    # Schnittmenge:
    set_4 = set_1 & set_2
    print(set_4)
    
    # Vereinigungsmenge:
    set_5 = set_1 | set_2
    print(set_5)
    
    # Differenzmenge:
    set_6 = set_1 \ set_2
    print(set_6)
    
    # Symmetrische Differenz (Entweder-Oder):
    set_7 = set_1 ^ set_2
    print(set_7)
    
    # Test, ob set_1 eine Obermenge von set_2 ist:
    istObermenge = set_1 > set_2
    print(istObermenge)

    Es existieren die folgenden speziellen Funktionen für Sets:

  • set.add() zum Hinzufügen von Elementen zu einer Menge hinzufügen.
  • set.discard() zum Entfernen von Elementen aus einer Menge.
  • set.copy() zum Erstellen einer Kopie einer Menge.
  • set.clear zum Löschen aller Elemente einer Menge, wobei sie selbst definiert bleibt.
  • Analog zu einem Tupel kann auch eine unveränderliche Menge erzeugt werden: frozenset()

    dict – Wörterbücher

    Hiermit werden key-value-Paare unterstützt; ein bestimmter key verweist auf einen value (Eintrag). Dabei entsteht ein sogenanntes Dictionary, in Kurzform dict Zur Darstellung von dict werden in Python geschweifte Klammern verwendet. Schlüssel und zugehörige Werte werden durch einen Doppelpunkt voneinander getrennt. Die einzelnen Schlüssel-Wert-Paare entsprechen einer Liste und werden daher durch Komma voneinander getrennt.

    gehaltsliste = {
        "Müller"        : 3414.15,
        "Meyer"         : 1414.12,
        "Schnasebeutel" : 2452.03,
        "Krachulke"     : 3312.89,
        }
    print("Das Gehalt von Krachulke beträgt ",gehaltsliste["Krachulke"], "€",sep="")
    print("und das von Müller beträgt ",gehaltsliste["Müller"], "€",sep="")
    print()
    
    gehaltsliste["Schulze"] = 2342.12 # Zur Gehaltsliste hinzufügen
    gehaltsliste.update( {"Schnasebeutel" : 2452.13 } )
    summeGehalt = 0
    for i in gehaltsliste.values():
      summeGehalt += i
    print("Die gesammte Summe an Gehältern beträgt ",summeGehalt, "€",sep="")
    print()
    
    sortedListe = dict(sorted(gehaltsliste.items()))#  nur für Python Version > 3.6
    
    txt = "{:14} {:.2f}"
    for key, value in sortedListe.items():
      print(txt.format(key, value))

    sorted(gehaltsliste.items()) liefert selbst kein Dictionary zurück, sondern eine Liste von Tupelpaaren. Mit dict() kann diese aber problemlos in ein Dictionary gewandelt werden:

    gehaltsliste = {
        "Müller"        : 3414.15,
        "Meyer"         : 1414.12,
        "Schnasebeutel" : 2452.03,
        "Krachulke"     : 3312.89,
        }
    sortedListe = sorted(gehaltsliste.items())
    print(type(sortedListe))
    print(sortedListe)
    print()
    dictSortedListe = dict(sorted(gehaltsliste.items()))# Um wandlung in ein dict
    print(type(dictSortedListe))
    print(dictSortedListe)

    Das Sortieren nach den zugewiesenen Werten (values) ist etwas umständlicher, da die Schlüssel, die auf diese verweisen, gesondert gehandhabt werden müssen:

    gehaltsliste = {
        "Müller"        : 3414.15,
        "Meyer"         : 1414.12,
        "Schnasebeutel" : 2452.03,
        "Krachulke"     : 3312.89,
        }
    print("Das Gehalt von Krachulke beträgt ",gehaltsliste["Krachulke"], "€",sep="")
    print("und das von Müller beträgt ",gehaltsliste["Müller"], "€",sep="")
    print()
    
    gehaltsliste["Schulze"] = 2342.12 # Zur Gehaltsliste hinzufügen
    gehaltsliste.update( {"Schnasebeutel" : 2452.13 } )
    summeGehalt = 0
    for i in gehaltsliste.values():
      summeGehalt += i
    print("Die gesammte Summe an Gehältern beträgt ",summeGehalt, "€",sep="")
    print()
    
    sortedListe = dict(sorted(gehaltsliste.items()))#  nur für Python Version > 3.6
    
    txt = "{:14} {:.2f}"
    print("Sortiert nach Namen:")
    for key, value in sortedListe.items():
      print(txt.format(key, value))
    
    print()
    print("Sortiert nach Gehalt:")
    sorted_values = sorted(gehaltsliste, key=gehaltsliste.get, reverse=True)
    for r in sorted_values:
      print(txt.format(r, gehaltsliste[r]))

    sorted(gehaltsliste, key=gehaltsliste.get, reverse=True) liefert selbst kein Dictionary zurück, sondern nur eine Liste der nach Values sortierten Keys zutück. Mit dict() kann diese aber nicht in ein Dictionary gewandelt werden, denn die Zuordnung key->value ist verloren gegangen. Die Werte der jeweiligen Keys sind aber nach wie vor in der Ausgangsliste gespeichert, sodass das Dictionary neu aufgebaut werden kann:

    gehaltsliste = {
        "Müller"        : 3414.15,
        "Meyer"         : 1414.12,
        "Schnasebeutel" : 2452.03,
        "Krachulke"     : 3312.89,
        }
    
    sorted_values = sorted(gehaltsliste, key=gehaltsliste.get, reverse=True)
    print(type(sorted_values))
    print(sorted_values)
    print()
    d_neu = {}
    for key in sorted_values:
      d_neu[key] = gehaltsliste[key]
    print(d_neu)
    

    Eine eingehende Beschreibung der verschiedenen Möglichkeiten zum Sortieren von dictionaries findet man in sorting_dicts.html. Eine Einführung zum Sortieren generell findet man in sorting.html.

    Dictionaries können ebenfalls zum "Übersetzen" (translate) von Textdateien genutzt werden: BEISPIELE

    Anstelle von Zeichenketten können auch Zahlen oder alle unveränderbaren Objekte genutzt werden. Veränderbare Objekttypen, wie Listen, sind als Schlüssel nicht erlaubt. Mit dictkeys(), dict.values() und dict.items() lassen sich so genannte „Views“ eines Wörterbuchs erzeugen. Bei einem View handelt es sich um eine Listenvariable, die automatisch aktualisiert wird, wenn das zugehörige dict geändert wird.

    Zusammenstellung der Dictionary Methoden
    Methode Beschreibung
    clear()Removes all the elements from the dictionary
    copy()Returns a copy of the dictionary
    fromkeys()Returns a dictionary with the specified keys and value
    get()Returns the value of the specified key
    items()Returns a list containing a tuple for each key value pair
    keys()Returns a list containing the dictionary's keys
    pop()Removes the element with the specified key
    popitem()Removes the last inserted key-value pair
    setdefault()Returns the value of the specified key. If the key does not exist: insert the key, with the specified value
    update()Updates the dictionary with the specified key-value pairs
    values()Returns a list of all the values in the dictionary

    Anwendungen

    Das folgende Beispiel benötigt die komma-separierte Liste Datenbank coop_coffee.csv. Speichern Sie diese auf Ihrem Rechner.

    # Beispiel coop_coffee.py
    #  benötigt die angegebenen Pakete
    #
    from matplotlib import pyplot
    import numpy
    import re
    
    data = numpy.recfromcsv('coop_coffee.csv', delimiter='\t',encoding="utf8")# array of tuple
    #print(data)
    #print(type(data))
    
    cat_names = ('misc', 'pieces', 'instant', 'grains', 'grinded')#  tuple
    #            Versch., Pads, Instant, Bohnen, gemahlen
    #print(type(cat_names))
    #print(cat_names)
    
    categories = dict((name, []) for name in cat_names)# dict name:[]
    #print(type(categories))
    #print(categories)
    
    categories['pieces'] = [row for row in data if re.search("pièces|portions|sachet|capsule|nescafé dolce gusto", row[2], re.IGNORECASE)]
    #print("pièces|portions|sachet|capsule|nescafé dolce gusto")
    #print(categories['pieces'])
    
    categories['instant'] = [row for row in data if re.search("soluble|instant", row[2], re.IGNORECASE)]#	Fertigkaffee
    categories['grains'] = [row for row in data if re.search("grains", row[2], re.IGNORECASE)]#		Bohnen
    categories['grinded'] = [row for row in data if re.search("moulu", row[2], re.IGNORECASE)]#		Gemahlt
    
    #print(sum(categories.values(), []))
    sum_categories_set = set([ tuple(t) for t in sum(categories.values(), []) ])
    #print(sum_categories_set)
    #print("sum_categories_set: ",type(sum_categories_set))
    
    categories['misc'] = set(list(data.tolist())) - sum_categories_set
    
    pyplot.gca().set_prop_cycle(color=['lightGray', 'red', 'blue', 'green', 'yellow'])# gca get-current-axis
    
    for name in cat_names:
        rows = categories[name]
        x = [r[0] for r in rows]
        y = [r[1] for r in rows]
        xy_label = "%s (%d)" % (name, len(rows))
        pyplot.plot(x, y, marker='o', alpha=0.75, linestyle='none', label=xy_label)
    
    pyplot.title("Coffee, Coop, July 2012")
    pyplot.xlabel("Price [CHF]")
    pyplot.ylabel("Weight [Kg]")
    pyplot.ylim(0, 1.05)
    pyplot.xlim(0, 21)
    pyplot.grid()
    pyplot.legend(numpoints=1, loc="right")
    
    pyplot.savefig('coop_coffee.png')
    pyplot.show()

    Lösungen der Übungen

    k = 1 # Startwert
    maxN = 1000
    for i in range(1, maxN): # Bereich 1,2,3,...maxN-1
      k = k * i              # n-1*n
      #print(k)              # Die Zahl n!
    print(len(str(k)))     # Anzahl Ziffern
    ## jetzt mit 10000 ##
    maxN = 10000
    for i in range(1, maxN): # Bereich 1,2,3,...maxN-1
      k = k * i              # n-1*n
      #print(k)              # Die Zahl n!
    print(len(str(k)))     # Anzahl Ziffern

    k = 1 # Startwert
    k0 = 0
    i = 0
    while True:
      i += 1
      k = k * i              # n-1*n
      l = len(str(k))
      if (l == 12345):
          print(str(i)+"! hat genau 12345 Stellen")
          break
      elif(l > 12345):
          print("\nEin n! mit genau 12345 Stellen existiert nicht!")
          print(str(i-1)+"! hat "+str(len(str(k0)))+" Stellen und "+str(i)+"! hat "+str(l)+" Stellen.")
          break
      k0 = k                 # n-1
    
    #print(k)

    Kurzzusammenfassung


    Nächste Kurseinheit: 02 Fallunterscheidungen