Heim  >  Artikel  >  Backend-Entwicklung  >  Einführung in die Methode zur dynamischen Definition von Funktionen in Python

Einführung in die Methode zur dynamischen Definition von Funktionen in Python

不言
不言nach vorne
2019-03-19 09:19:092694Durchsuche

Dieser Artikel bietet Ihnen eine Einführung in die Methode zum dynamischen Definieren von Funktionen in Python. Ich hoffe, dass er für Sie hilfreich ist.

Unter der MIT-Lizenz

In Python gibt es keinen syntaktischen Zucker, der die Funktionsdefinition zur Laufzeit vereinfacht. Dies bedeutet jedoch nicht, dass dies unmöglich oder schwierig zu erreichen ist.

from types import FunctionType

foo_code = compile('def foo(): return "bar"', "<string>", "exec")
foo_func = FunctionType(foo_code.co_consts[0], globals(), "foo")

print(foo_func())

Ausgabe:

bar

Analyse

Wenn Sie den Code Zeile für Zeile betrachten, werden Sie sehen, wie fragil die Sprach-/Dolmetscherbarriere ist.

>>> from types import FunctionType

Die Python-Dokumentation listet im Allgemeinen keine Funktionen auf, die nicht für manuell erstellte Klassen vorgesehen sind (was völlig vernünftig ist). Es gibt drei Möglichkeiten, dieses Problem zu lösen: help(), inspect (integrierte Methoden können nicht überprüft werden) und die endgültige Lösung besteht darin, den CPython-Quellcode zu überprüfen. (Empfohlen: Python-Tutorial)

In diesem Fall können sowohl help() als auch inspect die Arbeit erledigen, aber ein Blick auf den tatsächlichen Quellcode verrät mehr über die Datentypdetails.

>>> from inspect import signature
>>> signature(FunctionType)
<Signature (code, globals, name=None, argdefs=None, closure=None)>

1. Code

ist intern ein PyCode-Objekt, das für die Außenwelt als „types.CodeType“ offen ist. Nicht integrierte Methoden verfügen über ein __code__-Attribut, das das entsprechende Codeobjekt speichert. Types.CodeType-Objekte können zur Laufzeit mit der integrierten Methode „compile()“ erstellt werden.

2. Globals

Wenn eine Funktion auf eine Variable verweist, die nicht lokal definiert ist, sondern als Parameter übergeben, durch einen Standardparameterwert bereitgestellt oder durch einen Abschlusskontext bereitgestellt wird, wird sie verwendet wird im Globals-Wörterbuch suchen.

Die integrierte Methode globals() gibt einen Verweis auf die globale Symboltabelle des aktuellen Moduls zurück und kann daher verwendet werden, um ein Wörterbuch bereitzustellen, das immer mit dem Status der aktuellen Tabelle konsistent ist. Es ist auch möglich, ein beliebiges anderes Wörterbuch zu übergeben (FunctionType((lambda: bar).__code__, {"bar" : "baz"}, "foo")() == "baz").

3. Name (optional)

Steuern Sie das __name__-Attribut der zurückgegebenen Funktion. Nur wirklich nützlich für Lambdas (die aufgrund der Anonymität normalerweise keine Namen haben) und Umbenennungsfunktionen.

4. argdefs (optional)

Bietet eine Möglichkeit, Standardargumentwerte bereitzustellen, indem ein Tupel übergeben wird, das Objekte eines beliebigen Typs enthält (def foo(bar="baz" )). (FunctionType((lambda bar: bar).__code__, {}, "foo", (10,))() == 10).

5. Abschluss (optional)

(sollte wahrscheinlich nicht berührt werden, wenn es in anderen Python-VMs als CPython (PyPy, Jython,...) ausgeführt werden muss, da es stark davon abhängt Einzelheiten zur Implementierung).

Ein Tupel von Zellobjekten. Das Erstellen eines Zellobjekts ist nicht ganz einfach, da es Aufrufe der internen Komponenten von CPython erfordert, aber es gibt eine Bibliothek, die es einfacher macht: exalt (schamlose Werbung). (Anmerkung: Diese Bibliothek wurde vom Autor entwickelt.)

>>> foo_code = compile('def foo(): return "bar"', "<string>", "exec")

compile() ist eine integrierte Methode und daher auch gut dokumentiert.

Der Exec-Modus wird verwendet, da zum Definieren einer Funktion mehrere Anweisungen erforderlich sind.

>>> foo_func = FunctionType(foo_code.co_consts[0], globals(), "foo")

Aggregiert den gesamten Inhalt und weist einer Variablen eine dynamisch erstellte Funktion zu.

Die durch den vorherigen Codesatz kompilierte Funktion wird zur ersten Konstante des generierten Codeobjekts, daher reicht es nicht aus, nur auf foo_code zu verweisen. Dies ist eine direkte Folge des Exec-Modus, da das generierte Codeobjekt mehrere Konstanten enthalten kann.

>>> print(foo_func())

Dynamisch generierte Funktionen können wie andere Funktionen aufgerufen werden.

Abschließend

Außer bei Experimenten gibt es nur sehr wenige Szenarien, in denen dynamisch erstellte Funktionen benötigt werden.
Das Herumspielen mit Pythons Interna ist eine großartige Möglichkeit, mehr über die Sprache zu lernen.
Überschreiten Sie bei Bedarf mühelos Dolmetscher-/Sprachgrenzen.


Das obige ist der detaillierte Inhalt vonEinführung in die Methode zur dynamischen Definition von Funktionen in Python. Für weitere Informationen folgen Sie bitte anderen verwandten Artikeln auf der PHP chinesischen Website!

Stellungnahme:
Dieser Artikel ist reproduziert unter:segmentfault.com. Bei Verstößen wenden Sie sich bitte an admin@php.cn löschen