Python Tutorial, Teil 3

Schleifen und wiederverwendbare Funktionen

| Autor / Redakteur: Thomas Drilling / Stephan Augsten

Im dritten Teil des Python-Tutorials befassen wir uns mit Schleifen und Funktionen.
Im dritten Teil des Python-Tutorials befassen wir uns mit Schleifen und Funktionen. (Bild: Python.org)

Erste Schritte im „echten“ Programmieren erfordern es, mit den Möglichkeiten der Ablaufsteuerung und dem Erzeugen von wiederverwendbarem Code, neudeutsch „Funktionen“ vertraut zu sein. Wie dies unter Python funktioniert, sehen wir uns heute an.

Mit den grundlegenden Konzepten von Python haben wir uns bereits in den ersten beiden Teilen dieser Serie vertraut gemacht. Als gegeben nehmen wir nun noch hin, dass Python wie jede andere Programmiersprache auch eine Reihe von Grundrechenarten beherrscht, durch das math-Modul kommt eine große Anzahl komplexer mathematischer Funktionen hinzu (wir werden uns das Modul später noch ansehen).

Dieser dritte Teil unserer Python-Workshop-Reihe vollzieht einen großen Sprung hin in Richtung echter Programmierung, indem wir das bisher Gelernte mit Kontrollstrukturen, bedingten Anweisungen (if) und Funktionen kombinieren. Dies ermöglicht es, das Gelernte und zu Lernende anhand interessanterer und komplexere Programmierbeispiele zu erforschen.

Schleifen binden

Kontrollstrukturen (Schleifen) sind in jeder Sprache bekannt und sollen hier nicht in jeder Variante bis ins syntaktische Detail dekliniert werden. Das folgende Beispiel, die Ausgabe der Fibonacci-Folge (Dan Brown lässt grüßen), findet sich zugegebenermaßen in vielen Python-Tutorials wieder, was sicher daran liegt, dass Python im wissenschaftlichen Umfeld entstanden ist.

# Fibonacci-Reihe: Summe zweier folgender Elemente ergibt das Naechste.
x, y = 0, 1
while y < 1000:
   print (y)
   x, y = y, x+y

Das Beispiel gibt uns die Möglichkeiten gleich mehrere Konzepte in einem Rutsch zu erläutern. Zunächst ist eine Schleife (hier while) hinsichtlich der in Teil 1 und 2 beschriebenen Formalismen von Python ein Anweisungsblock, zu erkennen am Doppelpunkt hinter den Anweisungskopf und den Einrückungen der Befehle, die „im“ Anweisungsrumpf ausgeführt werden.

Eine while-Schleife wird durchlaufen, solange die angegebene Bedingung (hier: y < 10) „true“ (wahr) bleibt. Dazu muss man wissen, dass in Python jede nicht-negative ganze Zahl „true“ und Null als „false“ gilt, genau wie in C. In Python darf die Bedingung allerdings auch ein String, eine Liste oder eine beliebige Sequenz sein, wobei alles mit einer Länge verschieden von Null als „true“ gilt. Leere Sequenzen sind hingegen „false“.

Zum Formulieren einer Bedingung gehört auch ein Vergleichsoperator. In Python werden Vergleichsoperatoren wie in C formuliert, also <, >, ==, <=, >= und !=, wobei uns das „==“ bereits im zweiten Teil schon einmal begegnet ist. Das Beispiel enthält (in Zeile 1) ein weiteres bisher noch nicht bekanntes Konzept, die Mehrfachzuweisung. Mit …

x, y = 0, 1

… erhalten die beiden Variablen x und y gleichzeitig ihre Werte 0 bzw. 1 für x und y. Das Konstrukt wiederholt sich noch einmal in der letzten Zeile, wobei hier der Wert für y eine Berechnung enthält (x+y), was wiederum in Erinnerung an Teil 2 genau deshalb funktioniert, weil der Ausdruck auf der rechten Seite einer Zuweisung ausgewertet wird, „bevor“ die eigentliche Zuweisung passiert.

Print ist nicht gleich Print

Die print-Anweisung in Zeile 4 kennen wir ebenfalls schon. Print gibt den Wert des Ausdrucks aus, den es übergeben bekommt, hier den Inhalt einer Variablen. Zur Erinnerung: In Python 3 ist „print“ eine Funktion und keine Anweisung mehr, wie in Python 2.x. Deshalb müssen Argumente, wie bei jeder anderen Funktion auch, in einem Klammerpaar stehen, auch wenn es sich nur um eine Variable handelt.

Einfache Umsetzung der Fibonacci-Folge für Zahlen unter 1000.
Einfache Umsetzung der Fibonacci-Folge für Zahlen unter 1000. (Bild: Drilling)

Die print-Funktion gibt übrigens beliebig viele Werte ("value1, value2, ...") aus, welche durch Komma getrennt werden. Bei der Ausgabe werden die Werte per Default durch ein Leerzeichen getrennt. Nach dem Ausgeben des Wertes oder der Werte beendet die print-Funktion die Ausgabe stets mit einem Newline, wie die vorangestellte Abbildung zeigt.

Es ist aber möglich, dem Schlüsselwortparameter „end“ einen beliebigen String zuweisen. Dieser wird dann an Stelle des Default-Wert „\textbackslash n“ verwendet. Damit lassen sich dann problemlos mehrere Werte in einer Zeile ausgeben, z. B.

Eine sich wiederholende print-Funktion kann zur Ausgabe in einer Zeile gewzungen werden.
Eine sich wiederholende print-Funktion kann zur Ausgabe in einer Zeile gewzungen werden. (Bild: Drilling)

# Fibonacci-Reihe: Summe aufeinander-
# folgender Elemente ergibt das Naechste.
x, y = 0, 1
while y < 1000:
   print (y, end=" ")
   x, y = y, x+y

Zählschleifen

Neben Schleifen mit Abbruchbedingung (while), gibt es auch in Python Schleifen mit definiertem Zähler (for). Allerdings sind Syntax und Semantik von for-Schleifen in den einzelnen Programmiersprachen doch recht unterschiedlich. So gibt es beispielsweise die klassische Zählschleife mit einer durch einen Startwert initialisierten Schleifenvariablen in Python in dieser Form nicht

Das liegt daran, dass for-Schleifen in den meisten anderen Sprachen lediglich als eine Art Variante für while-Schleifen sind, während sie in Python tatsächlich zur Iteration über ein Sequenz von fast beliebigen Objekten dient. Python verwendet eine Art von for-Schleife, die ähnlich funktioniert wie in Perl oder der Bash, bei der nacheinander die Elemente einer Menge oder Liste bearbeitet werden, wozu diese einer Variablen zugewiesen werden. Die allgemeine Syntax lautet:

for Variable in Sequenz:
   Anweisung_1
   Anweisung_2
   ...
   Anweisung_x
else:
   Else-Anweisung_1
   Else-Anweisung_2
   ...
   Else-Anweisung_y

Einfache Umsetzung einer Zählschleife.
Einfache Umsetzung einer Zählschleife. (Bild: Drilling)

Praktisch könnte die Verwendung so aussehen

for x in [1,2,3,4,5]:
   print (x)

Der else-Zweig ist offensichtlich optional.

for x in [1,2,3,4,5]:
   print (x)
else: print (“Ende”)

Mit der „range“-Funktion besteht in Python darüber hinaus noch eine weitere einfache Möglichkeit, Zählschleifen zu emulieren. So erzeugt range() einen Iterator, der Zahlen in einem bestimmten Bereich (range), z. B. in einer einer for-Schleife liefern kann. Das sähe dann so aus

for x in range (1,11):
   print (x)

Selbstverständlich müssen Listen, bzw. Sequenzen nicht aus Zahlen bestehen. Auch so etwas geht:

for x in ["Montag","Dienstag","Mittwoch","Donnerstag","Freitag"]:
   print (x)
else: print ("Wochenende")

oder

for x in [128,64,32,16,8,4,2,1]:
   y = x + 1
print y

Funktionen in Python

In Programmiersprachen sind Funktionen eines der wichtigsten Strukturierungselemente. Sie erlauben das Gruppieren eine Reihe von Anweisungen, um diese im späteren Verlauf des Codes oder in einem anderen Programm wiederverwenden zu können. In anderen Programmiersprachen spricht man je nach Sprache von Prozeduren, Methoden, Routinen oder schlicht Unterprogrammen.

In Python werden Funktionen mit dem Schlüsselwort „def“ eingeleitet, gefolgt vom Funktionsnamen, einer Parameterliste in Klammern und dem obligatorischen Doppelpunkt, zur Kennzeichnung des dann eingerückten Anweisungsblocks der Funktion. Die Parameterliste besteht aus einem oder mehreren durch Komma separierten Bezeichnern. Diese Parameter werden beim Aufruf der Funktion aus dem "Hauptprogramm" auch Argumente genannt.

Die Fibonacci-Folge mit Zahlen bis zu einer vorgegebenen Grenze.
Die Fibonacci-Folge mit Zahlen bis zu einer vorgegebenen Grenze. (Bild: Drilling)

Die Funktionsdefinition ist beendet, wenn eine Anweisung erfolgt, die auf der gleichen Einrückungsstufe steht, wie der Kopf, wobei der Funktionskörper eine oder mehrere „return“-Anweisungen enthalten kann. Jede return-Anweisung beendet den Funktionsaufruf und liefert das Ergebnis des Ausdrucks, der hinter der return-Anweisung steht an die aufrufende Stelle zurück im Hauptprogramm.

Gibt es keine return-Anweisung, wird der spezielle Wert „none“ zurückgeliefert. Erreicht der Code das Ende des Funktionskörpers, ohne auf eine return-Anweisung zu treffen, endet der Funktionsaufruf und es wird der Wert „none“ zurückgeliefert. Mit diesen Kenntnissen können wie unsere eingangs erwähnt Fibonacci-Folge bis zur gewünschten Grenze (n) auch als Funktion formulieren:

def fibo(n): # Gib Fibonacci-Reihe bis n aus.
#"Fibonacci-Folge bis n"
x, y = 0, 1
while y < n:
   print (y, end=" ")
   x, y = y, x+y
# Rufe die gerade Fibo-Funktion für n=100 auf:
fibo(100)

Praxisbeispiel Bubblesort

Der Bubblesort-Algorithmus.
Der Bubblesort-Algorithmus. (Bild: Drilling)

Als abschließendes praxisnahes Beispiel soll ein beliebtes Sniplet aus der Algorithmik dienen, der Bubblesort-Sortier-Algorithmus in Python. Der Algorithmus dient dem aufsteigenden Sortieren der Elemente einer Liste. Dazu werden fortlaufend zwei benachbarte Elemente verglichen und gegebenenfalls vertauscht.

Mithilfe eine „logischen“ Variablen merken wir uns dabei, ob bei einem Durchlauf durch die Liste wenigstens einmal zwei Elemente vertauscht wurden. Nur wenn das „wahr“ ist, wird die Liste erneut durchlaufen, denn bei „falsch“ liegen die Elemente bereits in sortierter Reihenfolge vor. Umgangssprachlich sieht der Algorithmus etwa so aus:

Setze die Variable „vertauscht“ auf WAHR
Wiederhole die nachfolgenden Schritte solange, wie beim letzten Durchlauf wenigstens einmal vertauscht wurde:
   Setze die Variable vertauscht auf FALSCH.
   Vergleiche die 0. mit der 1. Zahl, dann die 1. mit der 2. Zahl,
      dann die 2. mit der 3. Zahl usw.
      und zuletzt die vorletzte mit der letzten Zahl u
      und vertausche die beiden verglichenen Zahlen, wenn sie nicht in der richtigen Reihenfolge stehen
      (das ist der Fall, wenn die erste größer als die zweite ist), und setze die Variable „vertauscht“ auf
      „WAHR“

Und das Ganze in Python:

def bubblesort(liste) :
anzahl = len(liste) # Anzahl der Elemente der Liste
vertauscht = 1 # WAHR
while vertauscht :
   vertauscht = 0 # FALSCH
   for index in range (0, -1+anzahl, 1) :
      if liste [index] > liste [index+1] :
         # Dann stehen die beiden Elemente nicht
         # in der richtigen Reihenfolge.
         wert = liste [index]
         liste [index] = liste [index+1]
         liste [index+1] = wert
         # Mit den drei Anweisungen werden die beiden
         # Elemente, die verglichen wurden, vertauscht.
         vertauscht = 1 # WAHR
return liste
print (bubblesort ([5,7,13,6,1,8,11,12]))

Kommentare werden geladen....

Kommentar zu diesem Artikel

Anonym mitdiskutieren oder einloggen Anmelden

Avatar
  1. Avatar
    Avatar
    Bearbeitet von am
    Bearbeitet von am
    1. Avatar
      Avatar
      Bearbeitet von am
      Bearbeitet von am

Kommentare werden geladen....

Kommentar melden

Melden Sie diesen Kommentar, wenn dieser nicht den Richtlinien entspricht.

Kommentar Freigeben

Der untenstehende Text wird an den Kommentator gesendet, falls dieser eine Email-hinterlegt hat.

Freigabe entfernen

Der untenstehende Text wird an den Kommentator gesendet, falls dieser eine Email-hinterlegt hat.

copyright

Dieser Beitrag ist urheberrechtlich geschützt. Sie wollen ihn für Ihre Zwecke verwenden? Infos finden Sie unter www.mycontentfactory.de (ID: 45153207 / IDEs & Programmiersprachen)