8.4 Methoden und Parameter 

Die bisher behandelten numerischen Datentypen waren sehr einfach aufgebaut: Ihre Werte ließen sich mit einer Zahl oder – bei complex – mit zwei Zahlen beschreiben, und der Umgang mit ihnen beschränkte sich auf Rechen-, Bit- und Vergleichsoperationen.
Im Folgenden werden wir uns mit umfassenderen Datentypen beschäftigen, für die es Operationen gibt, die nicht durch solche Operatoren abgebildet werden können. Um diese Funktionalität trotzdem zu ermöglichen, bedient man sich sogenannter Methoden. Methoden beziehen sich immer auf Instanzen bestimmter Datentypen und werden durch einen sogenannten Methodenaufruf verwendet. Der Aufruf einer Methode sieht folgendermaßen aus:
referenz.methode()
Das bedeutet dann: »Führe die von methode definierten Operationen mit der Instanz aus, auf die referenz verweist.« Welche Methoden für eine Instanz verfügbar sind, hängt von ihrem Datentyp ab.
Viele Methoden benötigen neben der Instanz noch weitere Informationen, um zu funktionieren. Hierfür gibt es sogenannte Parameter, die durch Kommata getrennt in die Klammern am Ende des Methodenaufrufs geschrieben werden:
referenz.methode(parameter1, parameter2)
Als Parameter können formal sowohl Referenzen als auch Literale verwendet werden:
var = 12 referenz.methode(var, "Hallo Welt!")
Es gibt auch optionale Parameter, die nur bei Bedarf übergeben werden müssen. Wenn wir Methoden mit solchen Parametern einführen, werden diese in der Parameterliste durch eckige Klammern gekennzeichnet:
referenz.methode(param1, param2[, param3])
In diesem Beispiel wären param1 und param2 reguläre, d. h. erforderliche Parameter, und param3 wäre ein optionaler Parameter. Die Methode könnte also mit zwei verschiedenen Konfigurationen aufgerufen werden:
referenz.methode(1, 2, 3) referenz.methode(1, 2)
Bei dem ersten Aufruf wäre der Wert 3 für den optionalen Parameter param3 übergeben worden, während er beim zweiten ausgelassen wurde.
Bei den bisher besprochenen Parameterübergaben war immer die Position eines Übergabewertes entscheidend dafür, für welchen formalen Parameter er eingesetzt wurde. Im letzten Beispiel stand die 1 als Übergabewert an erster Stelle und wurde dadurch mit dem ersten Parameter der Liste, param1, verknüpft. Gleiches gilt für die 2 und param2.
Man kann einer Methode Parameter auch als sogenannte Schlüsselwortparameter (engl. keyword arguments) übergeben. Schlüsselwortparameter werden direkt mit dem formalen Parameternamen verknüpft, und ihre Reihenfolge in der Liste spielt keine Rolle mehr. Um einen Wert als Schlüsselwortparameter zu übergeben, weist man dem Parameternamen innerhalb des Aufrufs den zu übergebenden Wert mithilfe des Gleichheitszeichens zu. Die beiden folgenden Methodenaufrufe sind demnach vollkommen gleichwertig:
>>> referenz.methode(1, 2, 3) >>> referenz.methode(param2=2, param1=1, param3=3)
Wie Sie sehen, spielt es dabei keine Rolle, ob es sich bei solchen Übergaben um optionale oder um erforderliche Parameter handelt. Man kann auch positions- und schlüsselwortbezogene Parameter mischen, wobei allerdings alle Schlüsselwortparameter am Ende der Parameterliste stehen müssen. Damit ist der nachstehende Aufruf äquivalent zu den beiden vorhergehenden:
>>> referenz.methode(1, param3=3, param2=2)
param1 wurde als positionsbezogener Parameter übergeben, während param2 und param3 als Schlüsselwortparameter übergeben wurden.
Welche der beiden Übergabemethoden man in der Praxis bevorzugt, ist größtenteils Geschmackssache. Schlüsselwortparameter haben den Vorteil, dass man nicht an die Reihenfolge der Parameter in der Funktionsdefinition gebunden ist. Deshalb bleiben solche Aufrufe auch dann noch korrekt, wenn sich die Parameterliste in ihrer Reihenfolge ändert. Außerdem sieht man schon an der Stelle des Aufrufs anhand des Parameternamens, wofür der übergebene Wert innerhalb der Funktion benutzt wird. Dadurch kann man die Lesbarkeit eines Programms verbessern. Demgegenüber ist die Übergabe positionsbezogener Parameter mit weniger Schreibaufwand verbunden, weil nicht immer der Parametername mit angegeben werden muss. Wenn sich die Namen der formalen Parameter in der Funktionsdefinition ändern, funktionieren positionsbezogene Übergaben auch ohne Änderung, wohingegen Übergaben mit Schlüsselwortparametern angepasst werden müssen. Es ist in der Regel so, dass positionsbezogene Parameter häufiger verwendet werden, was wahrscheinlich an dem geringeren Schreibaufwand liegt.
Die meisten Methoden erzeugen ein Ergebnis, das uns als Aufrufendem zur Verfügung steht. Beispielsweise verfügen Zeichenketten über eine Methode lower, mit deren Hilfe man einen neuen String erzeugen kann, in dem alle Großbuchstaben des Ursprungstrings in Kleinbuchstaben konvertiert wurden:
>>> s = "DaS sIeHt AbEr KoMiScH aUs" >>> s.lower() 'das sieht aber komisch aus'
Bei diesem sogenannten Rückgabewert der Methode handelt es sich um eine neue Instanz, in diesem Fall um eine String-Instanz, die wir wie gewohnt mit Referenzen versehen und anschließend weiterverwenden können:
>>> s = "DaS sIeHt AbEr KoMiScH aUs" >>> low = s.lower() >>> low.upper() 'DAS SIEHT ABER KOMISCH AUS'
Die Referenz low zeigt auf die von s.lower() zurückgegebene String-Instanz mit dem Wert 'das sieht aber komisch aus'. Wie alle Strings besitzt diese ihrerseits eine Methode upper, die alle Kleinbuchstaben in Großbuchstaben umwandelt und von uns mit low.upper() aufgerufen wird.
Neben diesen Methoden, die immer an einen bestimmten Datentyp gebunden sind, existieren Operationen, die global und damit unabhängig von bestimmten Typen zur Verfügung stehen. Sie werden Built-in Functions (dt. eingebaute Funktionen) genannt und sind fast genauso zu verwenden wie Methoden, außer dass ihnen keine Referenz auf eine Instanz vorangestellt werden muss und auch der Punkt entfällt. Die Instanz, auf die sich die Operation bezieht, wird in der Regel als Parameter übergeben.
builtin_name(referenz)
Sie haben schon solche Funktionen kennengelernt, wie zum Beispiel type und id in Abschnitt 7.1:
>>> t = type(1337) >>> t <type 'int'>