Funktionsrückgabewerte und Gültigkeitsbereich (Scope) in Python

PythonBeginner
Jetzt üben

Einführung

In diesem Lab vertiefen Sie Ihr Verständnis von Funktionen in Python, indem Sie deren Rückgabewerte und das Konzept des Variablen-Scopes (Geltungsbereichs) untersuchen. Sie beginnen damit, Funktionen zu betrachten, die keinen expliziten Rückgabewert haben, und beobachten, wie diese Aktionen ausführen, ohne ein Ergebnis zu erzeugen, das anderswo verwendet werden kann.

Anschließend lernen Sie, wie Sie Funktionen Rückgabewerte hinzufügen können, wodurch diese Ausgaben produzieren, die in Ihren Programmen erfasst und genutzt werden können. Das Lab führt Sie dann durch die Unterscheidung zwischen lokalen und globalen Variablen, das Verständnis ihrer jeweiligen Scopes und wie diese die Zugänglichkeit von Variablen innerhalb und außerhalb von Funktionen beeinflussen. Sie lernen auch, wie globale Variablen innerhalb von Funktionen mithilfe des Schlüsselworts global modifiziert werden können, und erkunden das Konzept der nonlocal-Variablen in verschachtelten Funktionen.

Funktionen ohne Rückgabewerte untersuchen

In diesem Schritt untersuchen wir Funktionen, die keine explizite return-Anweisung besitzen. Solche Funktionen führen eine Aktion aus, wie zum Beispiel das Drucken auf die Konsole, senden aber keinen Wert an den aufrufenden Programmteil zurück.

Suchen Sie zunächst im Dateiexplorer auf der linken Seite des WebIDE nach der Datei no_return_function.py. Doppelklicken Sie darauf, um sie im Editor zu öffnen.

Fügen Sie den folgenden Code in die Datei no_return_function.py ein:

def greet():
    print("Hello, welcome to the world of functions!")

## Call the function
greet()

Um dieses Skript auszuführen, öffnen Sie das integrierte Terminal, indem Sie im oberen Menü auf Terminal > New Terminal klicken. Führen Sie dann den folgenden Befehl aus:

python ~/project/no_return_function.py

Sie sehen die Ausgabe der Funktion, die auf der Konsole gedruckt wird:

Hello, welcome to the world of functions!

Die Funktion greet() führt die print()-Anweisung aus, erzeugt jedoch keinen Wert, der in einer Variablen gespeichert werden kann. Um zu sehen, was passiert, wenn Sie versuchen, das Ergebnis zu erfassen, modifizieren Sie die Datei no_return_function.py. Ersetzen Sie den bestehenden Inhalt durch den folgenden Code:

def greet():
    print("Hello, welcome to the world of functions!")

## Call the function and assign its result to a variable
result = greet()

## Print the value of the result
print(f"The result of calling greet() is: {result}")

Speichern Sie die Datei und führen Sie sie erneut im Terminal aus:

python ~/project/no_return_function.py

Die Ausgabe wird nun sein:

Hello, welcome to the world of functions!
The result of calling greet() is: None

Wie Sie sehen können, ist der Wert der Variablen result None. In Python gibt jede Funktion, die keine explizite return-Anweisung hat, automatisch None zurück. None ist ein spezieller Wert, der die Abwesenheit eines Wertes darstellt. Dies bestätigt, dass solche Funktionen wegen ihrer Nebeneffekte (wie dem Drucken) verwendet werden und nicht zur Erzeugung von Daten.

Rückgabewerte zu Funktionen hinzufügen

Im Gegensatz zum vorherigen Schritt sind die meisten Funktionen darauf ausgelegt, einen Wert zu berechnen und ihn an den Aufrufer zurückzugeben. Dies wird mithilfe des Schlüsselworts return erreicht. Eine return-Anweisung beendet die Funktion sofort und sendet einen angegebenen Wert zurück.

Öffnen Sie die Datei return_function.py aus dem Dateiexplorer in Ihrem WebIDE.

Fügen Sie den folgenden Code hinzu, um eine Funktion zu definieren, die zwei Zahlen addiert und deren Summe zurückgibt:

def add_numbers(a, b):
    """This function adds two numbers and returns the sum."""
    sum_result = a + b
    return sum_result

## Call the function and store the returned value
total = add_numbers(5, 3)

## Print the returned value
print(f"The sum is: {total}")

## Use the returned value in another operation
another_total = add_numbers(10, 20) * 2
print(f"Another calculated value: {another_total}")

Speichern Sie die Datei und führen Sie das Skript im Terminal aus:

python ~/project/return_function.py

Sie sollten die folgende Ausgabe sehen, die zeigt, dass die zurückgegebenen Werte erfolgreich erfasst und verwendet wurden:

The sum is: 8
Another calculated value: 60

Eine Funktion kann jedes Python-Objekt zurückgeben, einschließlich Zahlen, Zeichenketten (Strings), Listen und sogar Tupeln (Tuples). Die Rückgabe eines Tupels ist eine gängige Methode, um mehrere Werte gleichzeitig zurückzugeben.

Fügen Sie den folgenden Code am Ende Ihrer Datei return_function.py hinzu, um dies in Aktion zu sehen:

def get_user_info():
    """This function returns user information as a tuple."""
    name = "labex"
    age = 25
    city = "Virtual City"
    return name, age, city

## Call the function and unpack the returned tuple into separate variables
user_name, user_age, user_city = get_user_info()

## Print the unpacked values
print(f"Name: {user_name}, Age: {user_age}, City: {user_city}")

Speichern Sie die Datei und führen Sie sie erneut aus:

python ~/project/return_function.py

Die vollständige Ausgabe wird nun sein:

The sum is: 8
Another calculated value: 60
Name: labex, Age: 25, City: Virtual City

Hier gibt get_user_info() drei Werte zurück, die als Tupel verpackt sind. Der aufrufende Code entpackt dieses Tupel dann in drei separate Variablen, was die Arbeit mit mehreren Rückgabewerten erleichtert.

Lokale und globale Variablen unterscheiden

Das Verständnis des Variablenumfangs (Scope) ist entscheidend für das Schreiben von fehlerfreiem Code. Der Scope bestimmt, wo in Ihrem Programm auf eine Variable zugegriffen werden kann.

  • Globaler Scope: Variablen, die außerhalb einer Funktion definiert werden, sind global. Sie können von überall in Ihrem Skript darauf zugreifen.
  • Lokaler Scope: Variablen, die innerhalb einer Funktion definiert werden, sind lokal. Sie können nur von innerhalb dieser Funktion darauf zugreifen.

Lassen Sie uns dieses Konzept untersuchen. Öffnen Sie die Datei variable_scope.py im WebIDE.

Fügen Sie den folgenden Code in die Datei ein:

## Global variable
global_variable = "I am a global variable"

def my_function():
    ## Local variable
    local_variable = "I am a local variable"
    print(f"Inside the function:")
    print(f"  Accessing global_variable: {global_variable}")
    print(f"  Accessing local_variable: {local_variable}")

## Call the function
my_function()

## Try to access variables outside the function
print(f"\nOutside the function:")
print(f"  Accessing global_variable: {global_variable}")

## Attempting to access local_variable here would cause a NameError
## print(f"  Accessing local_variable: {local_variable}")

Speichern Sie die Datei und führen Sie sie im Terminal aus:

python ~/project/variable_scope.py

Die Ausgabe demonstriert die Zugänglichkeit jeder Variablen:

Inside the function:
  Accessing global_variable: I am a global variable
  Accessing local_variable: I am a local variable

Outside the function:
  Accessing global_variable: I am a global variable

Auf die globale Variable kann überall zugegriffen werden, aber die lokale Variable ist auf ihre Funktion beschränkt. Wenn Sie die letzte Zeile auskommentieren würden, würde das Skript mit einem NameError fehlschlagen.

Was passiert nun, wenn eine lokale Variable denselben Namen wie eine globale hat? Die lokale Variable "überschattet" (shadows) die globale, was bedeutet, dass sich der Name innerhalb der Funktion auf die lokale Variable bezieht.

Fügen Sie den folgenden Code am Ende Ihrer Datei variable_scope.py hinzu, um diesen Abschattungseffekt (Shadowing-Effekt) zu beobachten:

## Global variable
my_variable = "I am the global version"

def another_function():
    ## This local variable shadows the global one
    my_variable = "I am the local version"
    print(f"\nInside another_function(): {my_variable}")

## Call the function
another_function()

## The global variable remains unchanged
print(f"Outside another_function(): {my_variable}")

Speichern Sie und führen Sie das Skript erneut aus:

python ~/project/variable_scope.py

Die vollständige Ausgabe wird nun sein:

Inside the function:
  Accessing global_variable: I am a global variable
  Accessing local_variable: I am a local variable

Outside the function:
  Accessing global_variable: I am a global variable

Inside another_function(): I am the local version
Outside another_function(): I am the global version

Innerhalb von another_function() bezieht sich my_variable auf die lokale Version. Außerhalb bezieht es sich auf die globale Version. Die Zuweisung innerhalb der Funktion hatte keinen Einfluss auf die globale Variable.

Globale Variablen mit dem Schlüsselwort global modifizieren

Standardmäßig können Sie den Wert einer globalen Variablen nicht aus einer Funktion heraus ändern. Eine Zuweisungsanweisung innerhalb einer Funktion erstellt eine neue lokale Variable. Um eine globale Variable explizit zu ändern, müssen Sie das Schlüsselwort global verwenden.

Öffnen Sie die Datei modify_global.py im WebIDE.

Fügen Sie den folgenden Code hinzu, der einen globalen Zähler definiert und eine Funktion, um ihn zu inkrementieren:

## Global variable
counter = 0

def increment_counter():
    ## Declare that we intend to modify the global counter
    global counter
    counter += 1
    print(f"Inside function: counter is {counter}")

## Print the initial value
print(f"Before calling function: counter is {counter}")

## Call the function to modify the global variable
increment_counter()

## Print the value after the function call
print(f"After calling function: counter is {counter}")

Speichern Sie die Datei und führen Sie sie im Terminal aus:

python ~/project/modify_global.py

Die Ausgabe zeigt, dass die globale Variable erfolgreich geändert wurde:

Before calling function: counter is 0
Inside function: counter is 1
After calling function: counter is 1

Die Anweisung global counter teilt Python mit, dass jede Operation auf counter innerhalb dieser Funktion die globale Variable beeinflussen soll, nicht eine neue lokale.

Zum Vergleich fügen wir eine weitere Funktion hinzu, die das global-Schlüsselwort nicht verwendet. Fügen Sie den folgenden Code am Ende von modify_global.py hinzu:

def increment_counter_local():
    ## This assignment creates a new local variable named 'counter'
    counter = 100
    print(f"\nInside function (local): counter is {counter}")

## Print the global counter's value before the test
print(f"Before calling function (local test): counter is {counter}")

## Call the function
increment_counter_local()

## The global counter's value is unaffected
print(f"After calling function (local test): counter is {counter}")

Speichern Sie und führen Sie das Skript erneut aus:

python ~/project/modify_global.py

Die vollständige Ausgabe demonstriert den Unterschied deutlich:

Before calling function: counter is 0
Inside function: counter is 1
After calling function: counter is 1
Before calling function (local test): counter is 1
Inside function (local): counter is 100
After calling function (local test): counter is 1

Im zweiten Test beeinflusste die Zuweisung counter = 100 nur eine lokale Variable innerhalb von increment_counter_local(). Der globale counter behielt seinen Wert von 1.

nonlocal-Variablen in verschachtelten Funktionen verstehen

Die Scope-Regeln von Python gelten auch für verschachtelte Funktionen (eine Funktion, die innerhalb einer anderen Funktion definiert ist). Eine Variable, die für die innere Funktion nicht lokal ist, aber für die äußere Funktion lokal ist, wird als "nonlocal" (nicht-lokal) bezeichnet.

Um eine solche Variable aus der inneren Funktion zu ändern, müssen Sie das Schlüsselwort nonlocal verwenden. Dies ähnelt der Funktionsweise von global, gilt jedoch für verschachtelte Scopes anstelle des globalen Scopes.

Öffnen Sie die Datei nonlocal_variable.py im WebIDE.

Fügen Sie den folgenden Code hinzu, um die Verwendung von nonlocal zu demonstrieren:

def outer_function():
    outer_variable = "I am in the outer function"

    def inner_function():
        ## Declare that we are modifying the variable from the enclosing scope
        nonlocal outer_variable
        outer_variable = "I have been modified by the inner function"
        print(f"Inside inner_function(): {outer_variable}")

    print(f"Before calling inner_function(): {outer_variable}")
    inner_function()
    print(f"After calling inner_function(): {outer_variable}")

## Call the outer function
outer_function()

Speichern Sie die Datei und führen Sie sie im Terminal aus:

python ~/project/nonlocal_variable.py

Die Ausgabe zeigt, dass die innere Funktion die Variable der äußeren Funktion erfolgreich geändert hat:

Before calling inner_function(): I am in the outer function
Inside inner_function(): I have been modified by the inner function
After calling inner_function(): I have been modified by the inner function

Die Anweisung nonlocal outer_variable ermöglicht es inner_function, die Bindung von outer_variable aus outer_function neu zuzuweisen.

Sehen wir uns nun an, was passiert, wenn das nonlocal-Schlüsselwort fehlt. Fügen Sie den folgenden Code am Ende von nonlocal_variable.py hinzu:

def outer_function_local_test():
    outer_variable = "I am in the outer function (local test)"

    def inner_function_local_test():
        ## This assignment creates a new local variable
        outer_variable = "I am a local variable in inner_function"
        print(f"\nInside inner_function_local_test(): {outer_variable}")

    print(f"\nBefore calling inner_function_local_test(): {outer_variable}")
    inner_function_local_test()
    print(f"After calling inner_function_local_test(): {outer_variable}")

## Call the outer function for the local test
outer_function_local_test()

Speichern Sie und führen Sie das Skript erneut aus:

python ~/project/nonlocal_variable.py

Die vollständige Ausgabe hebt den Unterschied hervor:

Before calling inner_function(): I am in the outer function
Inside inner_function(): I have been modified by the inner function
After calling inner_function(): I have been modified by the inner function

Before calling inner_function_local_test(): I am in the outer function (local test)
Inside inner_function_local_test(): I am a local variable in inner_function
After calling inner_function_local_test(): I am in the outer function (local test)

Im zweiten Beispiel erzeugte die Zuweisung innerhalb von inner_function_local_test() eine neue lokale Variable, wodurch die outer_variable im umschließenden Scope unverändert blieb.

Zusammenfassung

In diesem Lab haben Sie mehrere Schlüsselkonzepte im Zusammenhang mit Python-Funktionen untersucht. Sie begannen damit, dass Funktionen ohne eine explizite return-Anweisung implizit None zurückgeben. Anschließend übten Sie die Verwendung des return-Schlüsselworts, um Werte aus einer Funktion zurückzugeben, einschließlich der Rückgabe mehrerer Werte als Tupel.

Sie haben sich auch mit dem Variablen-Scope (Gültigkeitsbereich) befasst und zwischen lokalen Variablen (nur innerhalb einer Funktion zugänglich) und globalen Variablen (im gesamten Skript zugänglich) unterschieden. Sie lernten, wie Shadowing (Abschattung) von Variablen funktioniert und wie das global-Schlüsselwort verwendet wird, um eine globale Variable aus einer Funktion heraus zu ändern. Schließlich haben Sie verschachtelte Funktionen untersucht und das nonlocal-Schlüsselwort verwendet, um Variablen in einem umschließenden, nicht-globalen Scope zu ändern.