Python: Prozeduren und Funktionen
► Python-Dokumentation: Function definitions
Prozeduren sind Programmteile, die nicht unmittelbar ausgeführt werden, sondern erst dann, wenn sie durch ihren Namen aufgerufen werden.
Mit ihrer Hilfe können wiederkehrende Aufgaben implementiert werden. Da sie nur ein einziges Mal notiert werden müssen, kann ein Skript auf diese Weise kürzer und übersichtlicher gehalten werden. Korrekturen an der Prozedur wirken sich so auch auf jede Stelle aus, an der diese aufgerufen wird.
Eine Prozedur wird mit der Anweisung def gefolgt von dem Prozedurnamen definiert. Für den Namen der Prozedur gelten die gleichen Regeln wie für den Namen einer Variable.
def meineProzedur():
pass
► Python-Dokumentation: pass
In diesem Beispiel wird die Prozedur meineProzedur() definiert. Die Anweisung pass dient lediglich als Platzhalter für den bislang fehlenden Inhalt. Sie hat die Bedeutung ›Tue nichts spezielles, sondern gehe zum nächsten Programmschritt‹.
Eine Prozedur muss immer vor ihrem Aufruf definiert sein.
Im folgenden Beispiel wird die Prozedur konkretisiert und in einer Zählschleife aufgerufen:
def meineProzedur():
print("Hallo Welt!")
for i in range(10):
meineProzedur()
An Prozeduren können auch Argumente übergeben werden, die innerhalb der Prozedur verarbeitet werden. Anzahl, Position und Datentyp der übergebenen Argumente müssen in der Grundform sowohl in der Definition der Prozedur als auch in ihrem Aufruf übereinstimmen.
def vol(l, b, h):
print("Das Volumen beträgt", float(l) * float(b) * float(h), "m³.")
laenge = input("Geben Sie die Länge in Metern ein: ")
breite = input("Geben Sie die Breite in Metern ein: ")
hoehe = input("Geben Sie die Höhe in Metern ein: ")
vol(laenge, breite, hoehe)
Die in einer Prozedur oder Funktion verarbeiteten Attribute können auch einen Vorgabewert besitzen. Ein solcher Wert kann im Aufruf der Prozedur bzw. Funktion dann weggelassen werden:
def vol(l, b, h = 10):
print("Das Volumen beträgt", float(l) * float(b) * float(h), "m³.")
vol(2, 4) # Für h wird der Vorgabewert 10 verwendet.
vol(2, 4, 20) # Für h wird der Wert 20 übergeben.
Die innerhalb einer Prozedur bzw. einer Funktion verwendeten Namen für Variablen gelten nur innerhalb dieser Prozedur oder Funktion, wie der NameError durch Zeile 6 demonstriert:
def vol(l, b, h):
v = float(l) * float(b) * float(h)
print("Das Volumen beträgt", v, "m³.")
volumen = vol(2, 4, 10)
print(v) # Diese Variable existiert nur innerhalb der Prozedur!
Allerdings können Prozeduren oder Funktionen Variablen aufrufen, die zwar nicht innerhalb, aber außerhalb der Prozedur bzw. Funktion bereits definiert wurden. Verändern lassen sich diese Werte nicht:
def test():
print(x)
x += 1 # Der Versuch einer Operation mit x führt zu einem UnboundLocalError
x = 100
test()
Variablen, die außerhalb einer Funktion definiert wurden, können zwar innerhalb einer Funktion nicht verändert werden, sie können dort aber neu definiert werden und sind dann eine neue Variable mit gleichem Namen. Der Wert der ursprünglichen Variable gleichen Namens außerhalb der Funktion bleibt unberührt.
Die Elemente bestimmter Datentypen wie Listen und Dictionarys innerhalb einer Prozedur bzw. einer Funktion können allerdings sehr wohl verändert werden können, auch wenn sie nicht an die Prozedur bzw. Funktion übergeben wurden und auch nicht an einen Rückgabewert gebunden sind, wie folgendes Beispiel veranschaulichen soll:
def test():
nm = 200
st = "Welt!"
li1[0] = "Affe"
li2 = ["Apfel", "Birne", "Orange"]
di1["Einwohner"] = 125000
di2 = {"Land":"Spanien", "Stadt":"Madrid", "Einwohner":3200000}
print(nm)
print(st)
print(li1)
print(li2)
print(di1)
print(di2)
nm = 100
st = "Hallo"
li1 = ["Hund", "Katze", "Maus"]
li2 = ["Baum", "Blatt", "Blüte"]
di1 = {"Land":"Schweiz", "Stadt":"Bern", "Einwohner":126000}
di2 = {"Land":"Italien", "Stadt":"Rom", "Einwohner":2800000}
test()
print()
print(nm)
print(st)
print(li1) # Die Liste wurde innerhalb der Funktion verändert.
print(li2)
print(di1) # Das Dictionary wurde innerhalb der Funktion verändert.
print(di2)
Funktionen
► Python-Dokumentation: Function definitions
Funktionen können als Sonderform der Prozeduren betrachtet werden, da eine Funktion mindestens einen Rückgabewert besitzt, der üblicherweise das Ergebnis der Verarbeitung der übergebenen Attribute enthält. Dieser Wert wird mit der Anweisung return zurückgegeben und kann so im weiteren Verlauf verarbeitet werden.
def vol(l, b, h):
v = float(l) * float(b) * float(h)
return v
laenge = input("Geben Sie die Länge in Metern ein: ")
breite = input("Geben Sie die Breite in Metern ein: ")
hoehe = input("Geben Sie die Höhe in Metern ein: ")
volumen = vol(laenge, breite, hoehe)
print("Das Volumen beträgt", volumen, "m³.")
Wie eine Funktion mit mehreren Rückgabewerten aufgerufen wird, soll folgendes Beispiel veranschaulichen:
def berechnung(x):
a = 1 * x
b = 2 * x
c = 3 * x
return a, b, c
e, f, g = berechnung(8)
print(e, f, g)
Mit Prozeduren und Funktionen lassen sich Skripte auch übersichtlich gestalten, so dass zusammenhängende Prozesse dicht beieinander liegen und durch den Namen klar erkennbar sind. So lässt sich beispielsweise der Ablauf eines Programms bereits zu Beginn seiner Entwicklung festlegen, auch wenn die konkreten Inhalte noch nicht implementiert worden sind:
def eingabe():
return True
def verarbeitung(data):
return True
def ausgabe(data):
pass
i = eingabe()
o = verarbeitung(i)
ausgabe(o)
Rekursive Funktionen
Rekursive Funktionen sind Funktionen, die sich selbst aufrufen. Ebenso wie bei Schleifen muss hier sichergestellt werden, dass es eine Abbruchbedingung gibt, die das Verlassen der Funktion auslöst, da die Rekursion nicht beliebig oft durchgeführt werden kann.
def hochzaehlen(x):
if x < 20:
print(x)
hochzaehlen(x + 1)
hochzaehlen(3)
Wie oft rekursiert werden kann, lässt sich folgendermaßen bestimmen. Der letzte ausgegebene Wert (995) entspricht der maximalen Tiefe der Rekursion:
def hochzaehlen(x):
print(x)
try:
hochzaehlen(x + 1)
except:
return
hochzaehlen(0)
Folgendes Skript ist ein weiteres Beispiel für eine rekursive Funktion, bei der die Inhalte eines Verzeichnisbaumes durchsucht werden. Findet die Funktion einen Unterordner, wird die Funktion rekursiv auf diesen Unterordner angewendet (Zeile 17). In diesem Beispiel wird der Bilder-Ordner durchsucht und nach Dateien gefiltert, deren Content-Typ mit image beginnt.
#!/usr/bin/python3
# -*- coding: utf-8 -*-
import os, magic
def scan_tree(dirname):
if (os.path.exists(dirname) == False or
os.path.isdir(dirname) == False or
os.access(dirname, os.R_OK) == False):
return False
else:
objects = os.listdir(dirname)
for objectname in objects:
objectpath = dirname + "/" + objectname
if os.path.isdir(objectpath) == True:
print(objectpath)
scan_tree(objectpath)
elif os.path.isfile(objectpath):
mime = magic.Magic(mime=True)
if mime.from_file(objectpath)[0:6] == "image/":
if os.access(objectpath, os.R_OK):
print(" ", objectname)
else:
print("Nicht lesbar.")
scan_tree(os.environ['HOME'] + "/Bilder")