Wieso soll man überhaupt ein Programm in Funktionen aufteilen? Zunächst bedeutet das schreiben der Funktion scheinbar einen Mehraufwand. Der Grund wird offensichtlich, wenn man ein wenig weiter schaut.
Das DRY-Prinzip lautet: Don't repeat yourself! Jedesmal wenn Sie den gleichen Code mehrfach schreiben, erhöht sich das Risiko von Fehlern. Angenommen Sie haben in Ihrem Programm den gleichen Codeteil 5x geschrieben. Nun stellen Sie fest, dass ein Fehler in diesem Codeteil ist oder Sie wollen etwas ergänzen. So ist die Gefahr gross, dass Sie die Korrektur 4x vornehmen und die letzte Stelle vergessen.
Daher wird alles, was Sie mehrfach benötigen, in eine Funktion gepackt.
Es ist einfacher ein Programm zu verstehen, wenn es in viele, klar definierte Teilaufgaben unterteilt ist. Ein Sourcecode mit mehreren hundert Zeilen an einem Stück, ist extrem schwer zu lesen.
Nachdem ein Programm geschrieben wurde, ist es oftmals jahrelang im Einsatz. Während dieser Zeit müssen Fehler korrigiert und weitere Funktionen eingebaut werden. Durch die Abgrenzung von Teilaufgaben wird das Programm übersichtlicher. Es ist auch Jahre später viel einfacher, Änderungen vorzunehmen.
Funktionen können sehr einfach wiederverwendet werden. Sie müssen also nicht jedes mal das ganze Programm neu erfinden. Vielmehr können sie Teile aus bestehenden Programmen übernehmen.
Beispielsweise stehen in Python Dutzende von Bibliotheken mit vorgefertigten Funktionen zur Verfügung. Diese Funktiomnen hat ein anderer Softwareentwickler erstellt und wir können Sie nun nutzen. Damit ersparen wir uns viele Stunden Arbeit.
Sie wollen einem Kollegen den Auftrag erteilen, ihnen einen Kaffee aus dem Automaten zu holen. Dieser Kollege weiss, wo der Automat steht und wie man den Kaffeeautomaten bedient.
Was muss ich dem Kollegen mitteilen bzw. mitgeben?
Was will ich erhalten?
Fassen wir das in Pseudocode zusammen könnte der Auftrag in etwa so aussehen:
money = 4.50 size = "Espresso" cream = False sugar = True cup = Cup() coffee = colleague.bring_coffee(money, size, cream, sugar, cup)
Nun gehen Sie daran, die Funktion zu realisieren. Dabei empfiehlt es sich, gezielt vorzugehen:
Als ersten Schritt überlegen Sie sich, welche Teilaufgabe diese Funktion erledigen soll. Diese Teilaufgabe muss sich in einem kurzen Satz prägnant umschreiben lassen. Unklare oder schwammig definierte Teilaufgaben führen in der Regel zu schlechten Funktionen.
Aus der Definition der Aufgabe lässt sich auch ein sinnvoller Name für die Funktion ableiten.
put_string
is_number
Aus dem Namen der Funktion soll sich also auch der Zweck der Funktion herleiten lassen (Sprechend sein). Funktionsnamen sind klein geschrieben. Handelt es sich um mehr als ein Wort, so ist die snake_case_schreibweise angebracht.
Jede Funktionsdefinition beginnt mit dem Wort def
um Python anzuzeigen, dass eine neue Funktion definiert wird.
def put_string(): ...
Zur Schnittstelle gehören auch die Parameter/Argumente, welche der Aufrufer an die Funktion weiter gibt. Jeder Parameter benötigt einen einmaligen Bezeichner
def check_login(username, password): # Korrekte Bezeichner ... def check_name_identical(name, name): # führt zu einem Fehler, da die Parameter identische Bezeichner haben
Zu jedem Paramter in der Schnittstelle wird innerhalb der Funktion automatisch eine lokale Variable deklariert.
Im Beispiel check_login
stehen also innerhalb der Methode die Referenzvariablen username
und password
zur Verfügung.
Beim Aufruf der Funktion gibt der Aufrufer die entsprechenden Werte für diese Variablen mit. Diese Werte werden automatisch in die entsprechenden lokalen Variablen gespeichert.
Das ist die Codezeile mit def
, dem Bezeichner und eventuellen (
Parameter/n)
abgeschlossen mit einem :
:
def is_number(number): ...
Alles was jetzt in die Funktion gehört muss identisch eingerückt sein. Normalerweise werden dafür 4 Leerzeichen verwendet.
Nun kommt der Kommentarblock mit den Angaben zur Funktion.
In vielen Entwicklungswerkzeugen wird ein Teil dieses Kommentarblocks automatisch erzeugt.
Erstellen Sie dazu drei Anführungzeichen „“„
unterhalb der Funktionsdeklaration und drücken Sie enter
def is_big(number): """ :param number: :return: """ }
Ergänzen Sie nun den generierten Docstring mit einer aussagekräftigen Beschreibung und der Beschreibung der Parameter und des Return-Wertes.
Falls sie keinen Return-Wert geplant haben, schreiben Sie None
hinter :return:
def is_big(number): """ Checks if a given number is a big number :param number (int): the number to check :return (bool): True or False depending on the size of the number """ def say_hello(): """ Just says 'Hello' :return: None """ def multiply(factor1, factor2): """ Multiplies the two numbers factor1 * factor2 :param factor1 (float): the first number :param factor2 (float): the second number :return product (float): product of the multiplication """
Können Sie die docstrings
nicht automatisch erzeugen, folgen Sie dieser Anleitung.
Weitere Ergänzungen zu den Kommentaren finden Sie in PEP 257 oder in den Coding-Guidelines des BZZ
Zuletzt programmieren Sie die Logik der Funktion. Betrachten Sie jede Methode wie ein eigenständiges kleines Programm, mit:
def is_big(number): """ Checks if a given number is a big number :param number (int): the number to check :return (bool): True or False depending on the size of the number """ threshold = 1000000 if number > threshold: return True else: return False def say_hello(): """ Just says 'Hello' :return: None """ print('Hello') def multiply(factor1, factor2): """ Multiplies the two numbers factor1 * factor2 :param factor1 (float): the first number :param factor2 (float): the second number :return product (float): product of the multiplication """ product = factor1 * factor2 return product
Rufen wir die Funktion nun auf, so müssen wir darauf achten, dass die Funktion vor dem Aufruf deklariert (geschrieben) ist.
Beispiel:
def is_big(number): """ Checks if a given number is a big number :param number (int): the number to check :return (bool): True or False depends on the size of the number """ threshold = 1000000 if number > threshold: return True else: return False def main(): is_it = is_big(123) print(is_it) if __name__ == '__main__': main()
False
Hinweis: In Python sollte die Funktionsdefinition immer vor dem Funktionsaufruf stehen. Andernfalls erhalten wir einen Fehler. Zum Beispiel:
def main(): is_it = is_big(123) print(is_it) if __name__ == '__main__': main() def is_big(number): """ Checks if a given number is a big number :param number (int): the number to check :return (bool): True or False depends on the size of the number """ threshold = 1000000 if number > threshold: return True else: return False
# NameError: name 'is_big' is not defined.