Tag 3: Funktionen & Standardbibliothek#

Bisher haben wir einzelne Code-Stücke geschrieben und nacheinander ausgeführt. Aus den vorherigen Tagen sind Sie bereits mit einigen Funktionen wie print(), len() oder range() vertraut.Python bietet viele eingebaute Funktionen wie diese, aber Sie können auch Ihre eigenen Funktionen schreiben.

Eine Funktion ist wie ein Miniprogramm innerhalb eines Programms. Funktionen können genutzt werden:

  • um komplexere Abschnitte zu kapseln

  • um wiederholt verwendete Funktionalität nicht mehrfach im Code zu haben

  • um Programme zu strukturieren

  • um anderen Leuten Funktionalität zur Verfügung zu stellen

Im Folgenden führen wir in Funktionen ein und wiederholen oder klären damit teilweise Inhalte der letzten Tage.

Funktionen#

Funktions-Definition#

Mit dem Schlüsselwort def können Funktionen definiert werden, gefolgt von einem Namen und eventuell Parametern. Das folgende Beispiel definiert eine Funktion namens hello_world().

def hello_world():
    print('Hi')

Formalisiert wäre eine Funktion:

def funktionsname(parameter):
    """ docstring - Beschreibung"""
    # statement(s)
    return value # optional

funktionsname(parameter) # Funktionsaufruf

Der erste Teil def funktionsname(parameter): wird auch Header genannt. Der eingerückte Teil wird Body genannt. Funktionen ermöglichen wiederholtes Nutzen von Funktionalitäten und das Teilen dieser Funktionalitäten mit Anderen. Zudem kann Code so besser organisiert und wiederverwendet werden - wie oben beschrieben.

Parameter und Rückgabewerte:#

Funktionen können Parameter akzeptieren und Werte zurückgeben, die mit dem return-Statement definiert werden. Die folgende Funktion addition akzeptiert zwei Parameter x und y und gibt das Resultat von x + y zurück.

def addition(x, y):
    return x + y

Um besser zu verstehen wie Funktionen funktionieren und wie wir selber welche schreiben können, erstellen wir nun eine einfache erste Version.

def hello(): # 'def' definiert eine Funktion, hello_world ist der Name der Funktion
    print('Hi')
    print('Guten Tag')

hello() # mit dem Namen und Klammern wird eine Funktion aufgerufen

# Ausgabe
# Hi
# Guten Tag

Hierbei wird die Funktion mit dem Schlüsselwort def eingeleitet. Der Funktion wird der Name hello_world gegeben und es werden keine Parameter übergeben (()). Durch die folgende Einrückung der print()-Aufrufe, ist klar, was zu Funktion gehört und was nicht. Der Funktionsaufruf hello() ist nicht mehr eingerückt und gehört somit nicht mehr zur Funktion. Dieser ruft dann die Funktion auf. Wichtig ist, dass Funktionen erst definiert werden müssen, bevor sie aufgerufen werden können. Das heisst, die Funktion muss im Code ‘über’ dem Aufruf stehen.

Die Möglichkeit, Funktionen Parameter “übergeben” zu können ermöglicht es beispielsweise auf Grundlage dessen Entscheidungen in der Funktion treffen zu können. So kann zum Beispiel entschieden werden, ob höflich oder leger gegrüßt werden soll.

def hello(hoeflich):
    if hoeflich == True:
        print('Guten Tag')
    else:
        print('Yo!')

hoeflich = True

hello(hoeflich) # Funktionsaufruf mit Parameter

# Ausgabe
# Guten Tag

Die Funktion von oben akzeptiert nun einen Parameter hoeflich. Dieser wird in dem if-else-Ausdruck verwendet um zu unterscheiden ob höflich gegrüßt wird (True) oder leger (False). Wichtig ist, dass im Aufruf hello(hoeflich) der Parameter entsprechend übergeben wird. Dieser muss nicht den selben Namen aufweisen - hello(True) würde genauso funktionieren.

Kommen wir nun zu dem Eingangsbeispiel der Addtion wieder.

def addition(x, y):
    add = x + y
    return add

Diese Funktion ermöglicht uns, eine einfache Addition wiederzuverwenden. Diese Funktion haben wir natürlich schon als Operator +, jedoch könnten in dieser Funktion beispielweise noch unterschiedliche Überprüfungen hinzugefügt werden So könnte geprüft werdten, dass es sich um einen Integer handeln muss, und mit Fehlern automatisch umgegangen werden (kommende Tage). Im Unterschied zur vorherigen Funktion gibt diese Funktion mit dem Schlüsselwort return etwas “zurück”. In diesem Fall die “Summe” von x und y. Da die Funktion etwas zurückgibt, kann mit ihrem Aufruf einer Variable ein neuer Wert zugewiesen werden.

Beispiel:

a = 5
b = 10
summe = addition(a, b)

Hier werden zwei Variablen a und b mit den Werten 5 und 10 initialisiert und als Parameter der Funktion addition übergeben. Diese werden in der Funktion der Reihenfolge nach den lokalen Variablen x (a) und y (b) zugewiesen. In der Funktion werden diese dann addiert und ‘zurückgegeben’. Damit wird mit der errechneten Summe der Addition in der Funktion nun die Variable summe initialisiert. summe hat somit den addierten Wert der beiden Variablen a und b.

Erforderliche und Optionale Parameter#

Funktionen können optionale Parameter haben, die beim Funktionsaufruf nicht mit übergeben werden müssen. Ein Beispiel haben Sie bereits kennengelernt, nämlich reverse=True in der list.sort()-Funktion. Dazu definieren wir einen Standard-Wert für den Parameter im Funktions-Header:

def hallo(sprache, nett=True):
    if sprache == 'DE':
        if nett:
            return "Moin"
        else:
            return "MoinMoin"
    else:
        if nett:
            return "Hello"
        else:
            return "HelloHello"

In diesem Beispiel hat die Funktion hallo() einen erforderlichen Parameter (den ersten, nämlich sprache und einen optionalen Parameter (den zweiten, nämlich nett). Für den Aufruf haben wir also zwei Möglichkeiten:

hallo('EN') # Gibt "Hello" zurück, "nett" hat den Standard-Wert von "True"
hallo('DE', False) #Gibt "MoinMoin" zurück

Im ersten Fall wird sprache beim Funktionsaufruf den Wert EN annehmen, nett den Standard-Wert von True. Im zweiten Fall werden beide Parameter übergeben, nett hat also den Wert False.

Wird die Funktion allerdings ohne Argument aufgerufen, erhalten wir einen Fehler:

>>> hallo()
Traceback (most recent call last):
  File "<input>", line 1, in <module>
    hallo()
TypeError: hallo() missing 1 required positional argument: 'sprache'

Python-Standardbibliothek#

Die Python-Standardbibliothek, auch bekannt als STDLIB, ist eine Sammlung von Modulen und Paketen, die mit Python geliefert werden und eine Vielzahl von nützlichen Funktionen und Werkzeugen für verschiedene Aufgaben bieten. Diese Bibliothek ist Teil der Python-Installation und muss nicht separat installiert werden.

Hier sind einige der Hauptbereiche, die von der Python-Standardbibliothek abgedeckt werden und was man damit machen kann:

  1. Betriebssystemoperationen (os): Das os-Modul bietet Funktionen zum Arbeiten mit dem Betriebssystem, einschließlich Dateioperationen, Verzeichnisoperationen, Umgebungsvariablen und Prozesssteuerung (morgen)

  2. Mathematische Funktionen (math): Das math-Modul enthält eine Vielzahl von mathematischen Funktionen und Konstanten, die für mathematische Berechnungen nützlich sind. Dazu gehören Funktionen für Trigonometrie, Logarithmen, Exponentialfunktionen, Runden und mehr.

  3. Zufallszahlen (random): Das random-Modul ermöglicht die Erzeugung von Pseudozufallszahlen. Es bietet Funktionen zum Generieren von Zufallszahlen, zur Auswahl von Zufallselementen aus Listen und zur Mischen von Sequenzen.

  4. Datum und Zeit (datetime): Das datetime-Modul bietet Klassen und Funktionen zum Arbeiten mit Datum und Zeit. Es ermöglicht das Erstellen, Manipulieren und Formatieren von Datum und Zeit sowie die Berechnung von Zeitdifferenzen.

  5. Dateiverarbeitung (io): Das io-Modul bietet Tools zum Lesen und Schreiben von Dateien und Datenströmen. Es ermöglicht das Arbeiten mit Dateien im Speicher sowie das Umleiten von Ein- und Ausgaben.

  6. Reguläre Ausdrücke (re): Das re-Modul stellt Funktionen und Klassen zum Arbeiten mit regulären Ausdrücken bereit. Reguläre Ausdrücke werden verwendet, um Textmuster in Zeichenketten zu suchen und zu manipulieren.

  7. Datenkompression (gzip, zipfile, zlib): Python bietet verschiedene Module zur Datenkompression, einschließlich gzip für GZIP-Komprimierung, zipfile für ZIP-Archive und zlib für die Verwendung des Zlib-Komprimierungsformats.

  8. Netzwerk- und Internetprotokolle (socket, urllib): Die socket- und urllib-Module ermöglichen die Kommunikation über Netzwerke und das Arbeiten mit Internetprotokollen wie HTTP, FTP und SMTP.

Diese Module müssen vor der Nutzung importiert werden. Das schauen wir uns am letzten Tag an.

Darüber hinaus bietet Python eine Reihe an sogenannten Methoden, die auf den eingebauten Datentypen operieren. Beispiele hierfür sind list.pop() oder list.remove(). Eine Methode ist auch eine Funktion, die allerdings an einen spezifischen Datentyp, ein Objekt oder eine Klasse (hierzu später mehr) gebunden ist. Methoden nutzen immer implizit den Wert oder das Objekt, dem sie zugeordnet sind. Das bezeichnen wir auch als den Wert, auf dem sie aufgerufen werden und das ist das, was vor dem . steht als Parameter.

Dies sind nur einige Beispiele für die Funktionen und Methoden, die in der Python-Standardbibliothek enthalten sind. Schauen Sie in die Dokumentation für mehr Informationen. Meistens ist es schneller, einfacher und besser solche Funktionen zu nutzen, als für den selben Zweck eigene Funktionen zu schreiben.

Tüftelspaß und Knobeleien#

Das war’s auch schon mit neuem Inhalt für heute. Jetzt ist Zeit zum Fragen stellen! Stellen Sie gern Fragen zu jeglichen Inhalten der letzten Tage - direkt im Plenum oder wie gehabt im allg. Markdown-Dokument.

Erste Tüfteleien

  1. Schreiben Sie eine Funktion division, die zwei Variablen nimmt, verarbeitet und das Ergebnis aus- und zurückgibt. Berechnen Sie mittels dieser Funktion das Ergebnis von: 8958937768937 geteilt durch 2851718461558. Was kommt raus?

  2. Schreiben Sie eine Funktion multiplikation und errechnen Sie mit dieser Funktion, wieviele Sekunden ein Jahr mit 365 Tagen hat.

  3. Nutzen Sie die Methoden der Standardbibliothek für Strings und finden Sie heraus, wieviele Buchstaben das Wort
    'Donaudampfschifffahrtselektrizitätenhauptbetriebswerkbauunternehmenbeamtengesellschaft' hat. Welcher Vokal ist am häufigsten vertreten? Wie oft?
    Schreiben Sie für jede dieser Zählungen oder Vergleiche eine eigene Funktion.

  4. Wie viele Buchstaben hat die ausgeschriebene Version der chemischen Formula Titin im Englischen? Welcher Buchstabe ist hier der häufigste? Nutzen Sie gern Ihre in Aufgabe 3 geschriebenen Funktionen.

Fortgeschrittenes Werkeln

  1. Machen Sie sich mit der Extra-Aufgabe am Ende von Tag 2 vertraut. Diese können Sie im Anschluss gern noch bearbeiten, gehen Sie dann jedoch bitte als Gruppe gemeinsam zu diesen Aufgaben über. Das Ziel dieser Aufgabe ist es, für alle Städte die Einwohnerdichte herauszufinden. Zunächst müssen jedoch die Daten “gereinigt” werden, also für die entsprechende Aufgabe so vorbereitet werden, dass eine Verarbeitung möglich ist.

  2. Sie finden in der Datengrundlage zwei Listen mit Informationen zu Flächen und Einwohnerzahlen. Diese sind ergänzende Informationen zu den Städten und Ländern der Extra-Aufgabe von gestern.

  3. Fügen Sie zunächst die Daten in Ihren Code ein und schauen Sie sich die Datengrundlage genauer an. Was muss mit den Daten passieren, damit Sie mit ihnen eine Einwohnerdichte berechnen können?

  4. Für die Fläche werden wir dies nun gemeinsam durchgehen, für die Einwohnerzahl ist es dann Ihnen überlassen, eine Lösung zu finden. Initialisieren Sie nun mit dem ersten Element der Flächen-Liste eine neue Variable und geben Sie sie aus. Bei der Fläche ist dies der Wert '0219 km²' an der Indexstelle ‘0’ der Liste. Um letztlich eine Berechnung von Fläche und Einwohnerzahl zu ermöglichen, müssen die Daten im Datentyp ‘float’ vorliegen. Die Daten liegen bisher aber noch als ‘String’ vor und sind somit noch nicht numerisch zu verarbeiten. Den Prozess einen Datentyp in einen anderen Datentyp zu verwandeln nennt sich casten. Das kann üblicherweise durchgeführt werden, indem der gewünschte Datentyp als Funktion auf den vorliegenden Werten ausgeführt wird:

    f1 = '0219'
    wert = float(f1)
    

    Probieren Sie dies gern im REPL aus und schauen was passiert.

  5. Versuchen Sie nun herauszufinden, woran es liegt, dass der String nicht in einen Gleitkommadatentyp (float) überführt werden kann. Das können Sie versuchen, indem Sie einzelne Teile des Wertes versuchen zu casten - so können Sie das Problem genauer definieren.

  6. Sie werden erkannt haben, dass einige Inhalte des Strings nicht konvertierbar sind. Anderes funktionieren jedoch überraschenderweise. Versuchen Sie dies nun auch mit einem anderen Wert der Datengrundlage ‘Fläche’. Das Ziel ist, sicher zu gehen, dass Ihre Methodik für alle Daten in der Datengrundlage das selbe Ergebnis liefert.

  7. Um nicht händisch jeden String im Folgenden überarbeiten zu müssen, sollten Sie nun versuchen einen Weg zu finden, wie Sie das automatisch bewerkstelligen können. Sprechen Sie sich in Ihrer Gruppe ab und erörtern und testen Sie potentielle Möglichkeiten - gern auch im sogenannten Peer-Programming.

  8. Wenn Sie eine Lösung gefunden haben versuchen Sie diese nun auf alle Elemente in der Liste anzuwenden. Gegebenenfalls hilft Ihnen eine Kombination aus for-Schleife für den Zugriff auf jedes Element der Liste und eine Funktion, die den String entsprechend bearbeitet und wieder zurückgibt.

  9. Überprüfen Sie Ihr Ergebnis, indem Sie sich die neue Liste ausgeben lassen. Hat alles funktioniert?

  10. Nun sind Sie dran! Bereinigen Sie die Liste der Einwohnerzahlen.

  11. Schreiben Sie nun eine Funktion, um die Einwohnerdichte zu berechnen und testen Sie dies mit einzelnen Werten.

  12. Wenden Sie nun beide Listen auf die eben geschriebene Funktion an und errechnen Sie für alle Werte die Einwohnerdichte. Speichern Sie diese in einer neuen Liste einwohnerdichte.