Das Organisieren größerer Programme mit Funktionen

PythonPythonIntermediate
Jetzt üben

This tutorial is from open-source community. Access the source code

💡 Dieser Artikel wurde von AI-Assistenten übersetzt. Um die englische Version anzuzeigen, können Sie hier klicken

Einführung

Wenn Ihre Programme größer werden, möchten Sie sich organisieren. In diesem Abschnitt werden Funktionen und Bibliotheksmodule kurz vorgestellt. Die Fehlerbehandlung mit Ausnahmen wird ebenfalls behandelt.

Dies ist ein Guided Lab, das schrittweise Anweisungen bietet, um Ihnen beim Lernen und Üben zu helfen. Befolgen Sie die Anweisungen sorgfältig, um jeden Schritt abzuschließen und praktische Erfahrungen zu sammeln. Historische Daten zeigen, dass dies ein Labor der Stufe Fortgeschrittener mit einer Abschlussquote von 74% ist. Es hat eine positive Bewertungsrate von 100% von den Lernenden erhalten.

Benutzereigene Funktionen

Verwenden Sie Funktionen für Code, den Sie wiederverwenden möchten. Hier ist eine Funktionsdefinition:

def sumcount(n):
    '''
    Gibt die Summe der ersten n ganzen Zahlen zurück
    '''
    total = 0
    while n > 0:
        total += n
        n -= 1
    return total

Um eine Funktion aufzurufen.

a = sumcount(100)

Eine Funktion ist eine Reihe von Anweisungen, die eine bestimmte Aufgabe ausführen und ein Ergebnis zurückgeben. Das Schlüsselwort return ist erforderlich, um den Rückgabewert der Funktion explizit anzugeben.

Bibliotheksfunktionen

Python kommt mit einer großen Standardbibliothek. Bibliotheksmodule werden mit import abgerufen. Beispielsweise:

import math
x = math.sqrt(10)

import urllib.request
u = urllib.request.urlopen('http://www.python.org/')
data = u.read()

Wir werden Bibliotheken und Module später im Detail behandeln.

Fehler und Ausnahmen

Funktionen melden Fehler als Ausnahmen. Eine Ausnahme bewirkt, dass eine Funktion abgebrochen wird und kann, wenn nicht behandelt, dazu führen, dass Ihr gesamtes Programm stoppt.

Versuchen Sie das in Ihrem Python-REPL.

>>> int('N/A')
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
ValueError: invalid literal for int() with base 10: 'N/A'
>>>

Zwecks Debugging beschreibt die Nachricht, was passiert ist, wo der Fehler aufgetreten ist und einen Stapelverlauf, der die anderen Funktionsaufrufe zeigt, die zum Fehler geführt haben.

Ausnahmen fangen und behandeln

Ausnahmen können gefangen und behandelt werden.

Um sie zu fangen, verwenden Sie den try - except-Befehl.

for line in file:
    fields = line.split(',')
    try:
        shares = int(fields[1])
    except ValueError:
        print("Couldn't parse", line)
  ...

Der Name ValueError muss mit der Art des Fehlers übereinstimmen, den Sie fangen möchten.

Es ist oft schwierig, genau vorher zu wissen, welche Arten von Fehlern auftreten können, je nachdem, welche Operation ausgeführt wird. Auf jeden Fall oder auf ungünstige Weise wird die Ausnahmebehandlung oft erst nachdem ein Programm unerwartet abstürzt (z.B. "oh, wir haben vergessen, diesen Fehler zu fangen. Wir sollten das behandeln!").

Ausnahmen auslösen

Um eine Ausnahme auszulösen, verwenden Sie den raise-Befehl.

raise RuntimeError('What a kerfuffle')

Dies wird dazu führen, dass das Programm mit einem Ausnahmentraceback abgebrochen wird. Es sei denn, es wird von einem try-except-Block gefangen.

% python3 foo.py
Traceback (most recent call last):
  File "foo.py", line 21, in <module>
    raise RuntimeError("What a kerfuffle")
RuntimeError: What a kerfuffle

Übung 1.29: Definieren einer Funktion

Versuchen Sie, eine einfache Funktion zu definieren:

>>> def greeting(name):
        'Issues a greeting'
        print('Hello', name)

>>> greeting('Guido')
Hello Guido
>>> greeting('Paula')
Hello Paula
>>>

Wenn der erste Ausdruck einer Funktion ein String ist, dient er als Dokumentation. Versuchen Sie, einen Befehl wie help(greeting) einzugeben, um ihn angezeigt zu sehen.

Übung 1.30: Ein Skript in eine Funktion umwandeln

Nehmen Sie den Code, den Sie für das pcost.py-Programm in Übung 1.27 geschrieben haben, und wandeln Sie ihn in eine Funktion portfolio_cost(filename) um. Diese Funktion nimmt einen Dateinamen als Eingabe, liest die Portfolio-Daten in dieser Datei und gibt die Gesamtkosten des Portfolios als Gleitkommazahl zurück.

Um Ihre Funktion zu verwenden, ändern Sie Ihr Programm so, dass es ungefähr so aussieht:

## pcost.py
def portfolio_cost(filename):
    """
    Berechnet die Gesamtkosten (Anteile * Preis) einer Portfolio-Datei
    """
    total_cost = 0.0

    with open(filename, "rt") as f:
        zeilen = f.readlines()
        headers = zeilen[0].strip().split(",")
        for zeile in zeilen[1:]:
            zeilen_daten = zeile.strip().split(",")
            nshares = int(zeilen_daten[1])
            price = float(zeilen_daten[2])
            total_cost += nshares * price

    return total_cost


import sys

if len(sys.argv) == 2:
    filename = sys.argv[1]
else:
    filename = input("Geben Sie einen Dateinamen ein:")

cost = portfolio_cost(filename)
print("Gesamtkosten:", cost)

Wenn Sie Ihr Programm ausführen, sollten Sie die gleiche Ausgabe wie zuvor sehen. Nachdem Sie Ihr Programm ausgeführt haben, können Sie Ihre Funktion auch interaktiv aufrufen, indem Sie Folgendes eingeben:

$ python3 -i pcost.py

Dies ermöglicht es Ihnen, Ihre Funktion im interaktiven Modus aufzurufen.

>>> portfolio_cost('portfolio.csv')
44671.15
>>>

Die Möglichkeit, interaktiv mit Ihrem Code zu experimentieren, ist nützlich für das Testen und Debuggen.

Übung 1.31: Fehlerbehandlung

Was passiert, wenn Sie Ihre Funktion auf eine Datei mit fehlenden Feldern ausprobieren?

>>> portfolio_cost('missing.csv')
Traceback (most recent call last):
    File "<stdin>", line 1, in <module>
    File "pcost.py", line 11, in portfolio_cost
    nshares    = int(fields[1])
ValueError: invalid literal for int() with base 10: ''
>>>

An diesem Punkt stehen Sie vor einer Entscheidung. Um das Programm zu machen, können Sie entweder die ursprüngliche Eingabedatei bereinigen, indem Sie schlechte Zeilen eliminieren, oder Sie können Ihren Code so ändern, dass er die schlechten Zeilen auf eine bestimmte Weise behandelt.

Ändern Sie das pcost.py-Programm, um die Ausnahme zu fangen, eine Warnmeldung auszugeben und die Verarbeitung der restlichen Datei fortzusetzen.

✨ Lösung prüfen und üben

Übung 1.32: Verwenden einer Bibliotheksfunktion

Python kommt mit einer großen Standardbibliothek von nützlichen Funktionen. Eine Bibliothek, die hier möglicherweise nützlich sein könnte, ist das csv-Modul. Sie sollten es verwenden, wenn Sie mit CSV-Datenfiles arbeiten müssen. Hier ist ein Beispiel, wie es funktioniert:

>>> import csv
>>> f = open('portfolio.csv')
>>> rows = csv.reader(f)
>>> headers = next(rows)
>>> headers
['name','shares', 'price']
>>> for row in rows:
        print(row)

['AA', '100', '32.20']
['IBM', '50', '91.10']
['CAT', '150', '83.44']
['MSFT', '200', '51.23']
['GE', '95', '40.37']
['MSFT', '50', '65.10']
['IBM', '100', '70.44']
>>> f.close()
>>>

Ein schönes Merkmal des csv-Moduls ist, dass es sich um eine Vielzahl von niedrigen Details wie Anführungszeichen und richtiges Komma-Splitten kümmert. In der obigen Ausgabe werden Sie bemerken, dass es die Anführungszeichen von den Namen in der ersten Spalte entfernt hat.

Ändern Sie Ihr pcost.py-Programm so, dass es das csv-Modul für die Analyse verwendet, und versuchen Sie, frühere Beispiele auszuführen.

✨ Lösung prüfen und üben

Übung 1.33: Einlesen von der Befehlszeile

Im pcost.py-Programm ist der Name der Eingabedatei im Code hartcodiert:

## pcost.py

def portfolio_cost(filename):
 ...
    ## Ihr Code hier
 ...

cost = portfolio_cost('portfolio.csv')
print('Gesamtkosten:', cost)

Das ist für das Lernen und Testen in Ordnung, aber in einem echten Programm würden Sie das vermutlich nicht tun.

Stattdessen könnten Sie den Dateinamen als Argument an ein Skript übergeben. Versuchen Sie, den unteren Teil des Programms wie folgt zu ändern:

## pcost_1.33.py

import csv


def portfolio_cost(filename):
    """
    Berechnet die Gesamtkosten (Anteile * Preis) einer Portfolio-Datei
    """
    total_cost = 0.0

    with open(filename, "rt") as f:
        zeilen = csv.reader(f)
        headers = next(zeilen)  ## Überspringe die Kopfzeile
        for zeile in zeilen:
            if len(zeile) < 3:
                print("Überspringe ungültige Zeile:", zeile)
                continue
            try:
                nshares = int(zeile[1])
                price = float(zeile[2])
                total_cost += nshares * price
            except (IndexError, ValueError):
                print("Überspringe ungültige Zeile:", zeile)

    return total_cost

import sys


if len(sys.argv) == 2:
    filename = sys.argv[1]
else:
    filename = 'portfolio.csv'

cost = portfolio_cost(filename)
print('Gesamtkosten:', cost)

sys.argv ist eine Liste, die die übergebenen Argumente auf der Befehlszeile enthält (sofern vorhanden).

Um Ihr Programm auszuführen, müssen Sie Python aus der Kommandozeile ausführen.

Beispielsweise aus bash auf Unix:

$ python3 pcost.py portfolio.csv
Gesamtkosten: 44671.15
bash %

Zusammenfassung

Herzlichen Glückwunsch! Sie haben das Lab zu Funktionen abgeschlossen. Sie können in LabEx weitere Labs ausprobieren, um Ihre Fähigkeiten zu verbessern.