Wie man prüft, ob eine Funktion in Python ein Generator ist

PythonPythonBeginner
Jetzt üben

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

Einführung

In diesem Lab lernen Sie, wie Sie Generatorfunktionen in Python identifizieren und die grundlegenden Unterschiede zwischen regulären Funktionen und Generatoren verstehen. Dieses Wissen ist entscheidend für das Schreiben von effizientem und speicherfreundlichem Code, insbesondere wenn Sie mit großen Datensätzen oder unendlichen Sequenzen arbeiten.

Das Lab führt Sie durch die Unterscheidung zwischen Funktionen und Generatoren, das Überprüfen ihrer Typen mit inspect.isgeneratorfunction und das Testen auf das Vorhandensein des Schlüsselworts yield. Sie erstellen ein Python-Skript, um die Unterschiede zu veranschaulichen und zu beobachten, wie Funktionen ein vollständiges Ergebnis zurückgeben, während Generatoren Werte iterativ liefern und die Ausführung bei Bedarf anhalten und fortsetzen.


Skills Graph

%%%%{init: {'theme':'neutral'}}%%%% flowchart RL python(("Python")) -.-> python/FunctionsGroup(["Functions"]) python(("Python")) -.-> python/ModulesandPackagesGroup(["Modules and Packages"]) python(("Python")) -.-> python/AdvancedTopicsGroup(["Advanced Topics"]) python/FunctionsGroup -.-> python/function_definition("Function Definition") python/ModulesandPackagesGroup -.-> python/standard_libraries("Common Standard Libraries") python/AdvancedTopicsGroup -.-> python/generators("Generators") subgraph Lab Skills python/function_definition -.-> lab-559519{{"Wie man prüft, ob eine Funktion in Python ein Generator ist"}} python/standard_libraries -.-> lab-559519{{"Wie man prüft, ob eine Funktion in Python ein Generator ist"}} python/generators -.-> lab-559519{{"Wie man prüft, ob eine Funktion in Python ein Generator ist"}} end

Unterscheidung zwischen Funktionen und Generatoren

In diesem Schritt lernen Sie die wichtigsten Unterschiede zwischen regulären Python-Funktionen und Generatoren kennen. Das Verständnis dieser Unterscheidung ist entscheidend für das Schreiben von effizientem und speicherfreundlichem Code, insbesondere wenn Sie mit großen Datensätzen oder unendlichen Sequenzen arbeiten.

Funktionen:

Eine Funktion ist ein Codeblock, der eine bestimmte Aufgabe ausführt. Wenn eine Funktion aufgerufen wird, führt sie ihren Code aus, führt möglicherweise Berechnungen durch und gibt einen Wert zurück (oder None, wenn keine explizite return-Anweisung vorhanden ist). Der Zustand der Funktion wird zwischen den Aufrufen nicht beibehalten.

Generatoren:

Ein Generator ist eine spezielle Art von Funktion, die das Schlüsselwort yield anstelle von return verwendet. Wenn ein Generator aufgerufen wird, gibt er ein Iterator-Objekt zurück. Jedes Mal, wenn Sie einen Wert vom Iterator anfordern, wird der Generator ausgeführt, bis er auf eine yield-Anweisung trifft. Der Generator hält dann an, speichert seinen Zustand und gibt den Wert zurück. Das nächste Mal, wenn ein Wert angefordert wird, setzt der Generator dort fort, wo er aufgehört hat.

Lassen Sie uns dies anhand eines Beispiels veranschaulichen. Erstellen Sie zunächst eine Datei namens function_vs_generator.py in Ihrem ~/project-Verzeichnis mit dem VS Code-Editor.

## ~/project/function_vs_generator.py

## Regular function
def square_numbers_function(numbers):
    result = []
    for number in numbers:
        result.append(number * number)
    return result

## Generator function
def square_numbers_generator(numbers):
    for number in numbers:
        yield number * number

## Example usage
numbers = [1, 2, 3, 4, 5]

## Using the function
function_result = square_numbers_function(numbers)
print("Function Result:", function_result)

## Using the generator
generator_result = square_numbers_generator(numbers)
print("Generator Result:", list(generator_result)) ## Convert generator to list for printing

Führen Sie nun das Python-Skript aus:

python ~/project/function_vs_generator.py

Sie sollten die folgende Ausgabe sehen:

Function Result: [1, 4, 9, 16, 25]
Generator Result: [1, 4, 9, 16, 25]

Sowohl die Funktion als auch der Generator liefern dasselbe Ergebnis. Der wichtigste Unterschied liegt jedoch darin, wie sie dies erreichen. Die Funktion berechnet alle Quadrate und speichert sie in einer Liste, bevor sie zurückgegeben werden. Der Generator hingegen gibt jedes Quadrat nacheinander nur dann zurück, wenn es angefordert wird.

Um den Unterschied noch deutlicher zu machen, ändern wir das Skript, um den Typ des zurückgegebenen Objekts auszugeben:

## ~/project/function_vs_generator.py

## Regular function
def square_numbers_function(numbers):
    result = []
    for number in numbers:
        result.append(number * number)
    return result

## Generator function
def square_numbers_generator(numbers):
    for number in numbers:
        yield number * number

## Example usage
numbers = [1, 2, 3, 4, 5]

## Using the function
function_result = square_numbers_function(numbers)
print("Function Result Type:", type(function_result))

## Using the generator
generator_result = square_numbers_generator(numbers)
print("Generator Result Type:", type(generator_result))

Führen Sie das Skript erneut aus:

python ~/project/function_vs_generator.py

Die Ausgabe wird sein:

Function Result Type: <class 'list'>
Generator Result Type: <class 'generator'>

Dies zeigt deutlich, dass die Funktion eine list zurückgibt, während der Generator ein generator-Objekt zurückgibt. Generatoren sind speicher-effizient, weil sie nicht alle Werte gleichzeitig im Speicher speichern. Sie generieren die Werte bei Bedarf.

Überprüfung des Typs mit inspect.isgeneratorfunction

Im vorherigen Schritt haben Sie den grundlegenden Unterschied zwischen Funktionen und Generatoren gelernt. Jetzt wollen wir untersuchen, wie Sie programmgesteuert feststellen können, ob eine Funktion eine Generatorfunktion ist, indem Sie die Methode inspect.isgeneratorfunction() verwenden. Dies ist besonders nützlich, wenn Sie mit Code arbeiten, bei dem Sie möglicherweise nicht über die Implementierungsdetails einer Funktion verfügen.

Das inspect-Modul in Python bietet Werkzeuge zur Introspektion, was bedeutet, dass Sie die internen Eigenschaften von Objekten wie Funktionen, Klassen, Modulen usw. untersuchen können. Die Methode inspect.isgeneratorfunction() überprüft speziell, ob ein gegebenes Objekt eine Generatorfunktion ist.

Lassen Sie uns die Datei function_vs_generator.py in Ihrem ~/project-Verzeichnis so ändern, dass diese Überprüfung enthalten ist. Öffnen Sie die Datei in VS Code und fügen Sie den folgenden Code hinzu:

## ~/project/function_vs_generator.py

import inspect

## Regular function
def square_numbers_function(numbers):
    result = []
    for number in numbers:
        result.append(number * number)
    return result

## Generator function
def square_numbers_generator(numbers):
    for number in numbers:
        yield number * number

## Check if it's a generator function
print("Is square_numbers_function a generator function?", inspect.isgeneratorfunction(square_numbers_function))
print("Is square_numbers_generator a generator function?", inspect.isgeneratorfunction(square_numbers_generator))

In diesem Code importieren wir zunächst das inspect-Modul. Dann verwenden wir inspect.isgeneratorfunction(), um sowohl die square_numbers_function als auch die square_numbers_generator zu überprüfen.

Führen Sie nun das Python-Skript aus:

python ~/project/function_vs_generator.py

Sie sollten die folgende Ausgabe sehen:

Is square_numbers_function a generator function? False
Is square_numbers_generator a generator function? True

Dies bestätigt, dass inspect.isgeneratorfunction() die Generatorfunktion korrekt identifiziert.

Diese Methode ist sehr nützlich, wenn Sie Funktionen unterschiedlich behandeln müssen, je nachdem, ob es sich um Generatoren oder reguläre Funktionen handelt. Beispielsweise möchten Sie möglicherweise über die Ergebnisse eines Generators iterieren, aber einfach eine reguläre Funktion aufrufen.

Überprüfung der Verwendung des yield-Schlüsselworts

In diesem Schritt werden wir uns darauf konzentrieren, wie die Anwesenheit des Schlüsselworts yield grundlegend eine Generatorfunktion definiert. Eine Funktion wird nur dann als Generator betrachtet, wenn sie mindestens eine yield-Anweisung enthält. Lassen Sie uns einen einfachen Test erstellen, um dies zu bestätigen.

Öffnen Sie die Datei function_vs_generator.py in Ihrem ~/project-Verzeichnis mit VS Code. Wir werden eine Funktion hinzufügen, die yield nicht verwendet, und sehen, wie sie sich verhält, wenn sie als potenzieller Generator behandelt wird.

## ~/project/function_vs_generator.py

import inspect

## Regular function
def square_numbers_function(numbers):
    result = []
    for number in numbers:
        result.append(number * number)
    return result

## Generator function
def square_numbers_generator(numbers):
    for number in numbers:
        yield number * number

## Function that returns a list, not a generator
def return_list(numbers):
    return [x for x in numbers]

## Check if it's a generator function
print("Is square_numbers_function a generator function?", inspect.isgeneratorfunction(square_numbers_function))
print("Is square_numbers_generator a generator function?", inspect.isgeneratorfunction(square_numbers_generator))
print("Is return_list a generator function?", inspect.isgeneratorfunction(return_list))

In diesem aktualisierten Code haben wir eine Funktion return_list hinzugefügt, die einfach eine Liste mithilfe einer Listen-Abstraktion zurückgibt. Sie enthält nicht das Schlüsselwort yield. Wir verwenden dann inspect.isgeneratorfunction(), um zu überprüfen, ob return_list eine Generatorfunktion ist.

Führen Sie nun das Python-Skript aus:

python ~/project/function_vs_generator.py

Sie sollten die folgende Ausgabe sehen:

Is square_numbers_function a generator function? False
Is square_numbers_generator a generator function? True
Is return_list a generator function? False

Wie erwartet wird return_list nicht als Generatorfunktion erkannt, da es das Schlüsselwort yield nicht verwendet. Dies zeigt, dass das Schlüsselwort yield für die Definition eines Generators in Python unerlässlich ist. Ohne es verhält sich die Funktion wie eine reguläre Funktion, gibt einen Wert (oder None) zurück und behält ihren Zustand zwischen den Aufrufen nicht bei.

Zusammenfassung

In diesem Lab haben Sie die grundlegenden Unterschiede zwischen regulären Python-Funktionen und Generatoren gelernt. Funktionen führen einen Codeblock aus und geben einen Wert zurück, während Generatoren mithilfe des Schlüsselworts yield ein Iterator-Objekt zurückgeben, das Werte nach Bedarf erzeugt und seinen Zustand zwischen den Aufrufen pausiert und speichert.

Sie haben untersucht, wie Generatoren ressourcenschonend sind, insbesondere bei der Verarbeitung großer Datensätze, da sie Werte nacheinander generieren, anstatt sie wie Funktionen alle im Speicher zu speichern. Das Lab hat diesen Unterschied anhand eines praktischen Beispiels der Quadrierung von Zahlen sowohl mit einer Funktion als auch mit einem Generator gezeigt.