9. Funktionen III

Warum Funktionen?

  • Zerlegen eines großen Problems in überschaubare Teilprobleme mit klaren Schnittstellen (d.h. es ist nur wichtig, was reinkommt und was rauskommt, nicht aber, wie es wirklich geschrieben ist)
  • Lokalität (d.h. Veränderungen von Code an einer Stelle werden im Allgemeinen nur dort Konsequenzen haben)
  • Wiederbenutzbarkeit (d.h. ein einmal gelöstes Teilproblem muss, wenn es wieder auftritt, nicht noch einmal gelöst werden)

Etwas überspitzt könnte man sagen, die Aufgabe eines/r ProgrammiererIn sei, Probleme in überschaubare Teile zu zerlegen, die dann einzeln implementiert werden können – eben zunächst in Funktionen, aber auch in Klassen und Module, wovon wir später hören werden. In jedem Fall ist diese Faktorisierung das, was am (guten) Programmieren eigentlich schwierig ist, und was noch für lange Zeit maschinell nicht zu machen sein wird. Auch die so oft geforderten “Ingenieursmethoden” bei der Softwareentwicklung können hier allenfalls eine Hilfestellung liefern.

Umgekehrt bleibt die Fähigkeit zu guter Faktorisierung euch erhalten, egal, in welcher Sprache ihr schließlich programmiert, denn auch wenn verschiedene Sprachen verschiedene Mittel bieten, das Grundproblem der gelungenen Problemanalyse teilen sie alle. In diesem Sinn ist das höchste Ziel dieses Kurses, euch ein Stück auf den Weg zu dieser Fertigkeit zu leiten.

Ein kleines Skript

def incString(s):
  i = int(s)
  i = i+1
  return str(i)

s = raw_input("Eine Zahl? ")
print incString(s)
print incString(raw_input(
  "Noch eine Zahl? "))

Laufen lassen:

examples> python simplescript.py
Eine Zahl? 18
19
Noch eine Zahl? -20
-19

Signaturen

Die Signatur einer Funktion sagt, welche Argumente sie bekommt und was sie zurückgibt, definiert also gerade die erwähnte Schnittstelle zwischen der Funktion und der “Außenwelt”. In Python werden sie konventionell so geschrieben:

<Funktionsname>(<Argumente>) -> <Ergebnistyp>

Das kann konkret so aussehen:

raw_input([prompt]) -> string
int(x[, base]) -> integer
str(object) -> string
len(object) -> integer

Für die Methoden von Strings:

S.count(sub[, start[, end]]) -> int
S.lower() -> string
S.replace (old, new[, maxsplit]) -> string

Für jedes Argument (von denen es offenbar auch mehr geben kann, sie werden dann durch Kommata getrennt) schreibt man also immer ein Wort, das andeuten soll, was die Bedeutung des Arguments (für die Funktion) ist. In eckigen Klammern sind dabei “optionale” (d.h., sie können übergeben sein oder auch nicht) Argumente angegeben. Bei unseren Beispielen zu replace hatten wir etwa nur zwei Argumente übergeben. Wir sehen hier, dass wir noch ein drittes hätten übergeben können. Was das dann bedeutet, entnimmt man der Dokumentation, zumal, wenn die Namensgebung so unglücklich ist wie hier: Ist das dritte Argument vorhanden, sollte es eine Zahl sein, die angibt, wie viele Vorkommen von old durch new maximal ersetzt werden sollen. Übergibt man etwa 1, wird nur das erste Vorkommen ersetzt (oder gar nichts, wenn old im String gar nicht vorkommt).

(Weiterführend:) In den Headern von C-Programmen stehen übrigens typischerweise ganz ähnliche Sachen, nämlich die so genannten Prototypen. Da C nicht Pythons dynamische Typisierung hat, muss darin allerdings immer noch der Typ jedes Arguments angegeben werden, und der Typ des Rückkehrwerts steht vor dem Funktionsnamen.

Control Flow

Code in Funktionen wird erst ausgeführt, wenn die Funktion aufgerufen wird. Der Control Flow (also die Reihenfolge, in der der Code durchlaufen wird) wird aber ziemlich konfus, wenn viele Funktionen aufgerufen werden. Python kann sich das merken, Menschen nicht. Deshalb:

Über Funktionen nicht im Control Flow nachdenken (“goto-Bild”), sondern in Schnittstellen: Was kommt rein, was kommt raus?

Übungen zu diesem Abschnitt

Ihr solltet euch wenigstens an den rötlich unterlegten Aufgaben versuchen

(1)

Wie ist die Signatur der incString-Funktion?

(2)

Verändert das “Hauptprogramm” des angegebenen Skripts zu

i = "23"
print incString(i)
print i

Was beobachtet ihr?


Markus Demleitner

Copyright Notice