[Road to Intermediate Python] Geben Sie die Ausführungsmethode dynamisch anhand des Variablennamens an

Link zur Zusammenfassung

https://qiita.com/ganariya/items/fb3f38c2f4a35d1ee2e8

Einführung

Um Python zu studieren, habe ich eine Group Intelligence Library namens acopy kopiert.

In acopy werden viele interessante Python-Grammatiken und -Sprachen verwendet, und es wird zusammengefasst, dass dies unter ihnen praktisch ist.

Dieses Mal konzentrieren wir uns darauf, die Ausführungsmethode dynamisch anhand des Variablennamens anzugeben.

getattr

In Python gibt es eine integrierte Funktion namens "getattr".

Sie können die Methode mit getattr (Instanz, Methodenname der Instanz) aus der Instanz abrufen.

Lassen Sie uns zunächst ein einfaches Beispiel versuchen.


class A:

    def __init__(self, msg):
        self.msg = msg

    def hello(self):
        print("hello ", self.msg)

    def add(self, x, y):
        return x + y


'''
hello  world
7
'''
a = A("world")
getattr(a, 'hello')()
print(getattr(a, 'add')(2, 5))

Schreiben wir einen einfachen Quellcode wie den oben genannten. Instanz a wird aus Klasse A generiert getattr (a, 'hello') ruft die Methode des Hallo-Attributs der Instanz a ab.

Durch anschließendes Hinzufügen von () wird die extrahierte Methode tatsächlich ausgeführt.

Erweiterte Version

Werfen wir einen Blick auf die tatsächliche Anwendung von getattr.

Dieses Mal haben Sie beschlossen, eine Klassenbibliothek namens Library zu erstellen. (Gerader Ball) In der Bibliothek wird eine eindeutige Verarbeitung von einer Funktion namens run ausgeführt, und interne Informationen werden vorerst in einer Mitgliedsvariablen namens "library_information" gespeichert.

Zu diesem Zeitpunkt haben Sie auch beschlossen, ein ** Plug-In ** zu verteilen, mit dem Sie anderen Benutzern, die die Bibliothek verwenden möchten, Zugriff auf die internen Informationen der Bibliothek gewähren.

Da es sich um eine von Ihnen erstellte Bibliothek handelt, können nur Sie den Hauptprozess implementieren. Durch Vorbereiten eines Prozesses zum Ausführen des Plug-Ins in der Ausführungsfunktion können Benutzer, die die internen Informationen der Bibliothek verwenden möchten, ihr eigenes Plug-In erstellen und weiter Es kann erweitert werden.

Schauen wir uns den Code an.

class Library:

    def __init__(self):
        self.plugins = []

        self.library_information = {
            'a': 10,
            'b': 20,
            'c': 30
        }

    def run(self):

        # plugin start
        self.call_plugins('start')

        for cycle in range(3):
            print("Library main process (Implementierung weggelassen)")

            # plugin iteration
            self.call_plugins('iteration')

        # plugin finish
        self.call_plugins('finish')

    def call_plugins(self, hook):
        for plugin in self.plugins:
            plugin(hook, **self.library_information)

    def add_plugin(self, plugin):
        self.plugins.append(plugin)


class Plugin:

    def __init__(self):
        pass

    def __call__(self, hook, **kwargs):
        getattr(self, f'on_{hook}')(**kwargs)

    def on_start(self, **kwargs):
        print(kwargs['a'])

    def on_iteration(self, **kwargs):
        print(kwargs['b'])

    def on_finish(self, **kwargs):
        print(kwargs['c'])


library = Library()
library.add_plugin(Plugin())
library.run()
'''
10
Library main process (Implementierung weggelassen)
20
Library main process (Implementierung weggelassen)
20
Library main process (Implementierung weggelassen)
20
30
'''

Bibliotheksklasse

Bibliothek ist eine Bibliothek, die Sie auf PyPI usw. erstellen und veröffentlichen möchten. Beachten Sie beispielsweise Numpy und Matplotlib.

Ich wollte in den internen Informationen der Bibliothek etwas namens "library_information" vorbereiten, damit es von Drittbenutzern verwendet und erweitert werden kann. ** Bereiten Sie daher ein Plug-In-Array als Mitgliedsvariable vor, erben Sie die Plug-In-Klasse und übergeben Sie sie an add_plugin, damit das Plug-In ausgeführt werden kann. Wenn das Plugin aus der Bibliothek ausgeführt wird, werden die internen Informationen der Bibliothek übergeben, sodass der Benutzer die Funktion erweitern kann. ** ** **

Plugin Klasse

Dieses Mal wird es mit print implementiert, aber ursprünglich ist es eine abstrakte Klasse, und Sie erstellen auch dieses Plugin, und der Benutzer erstellt das ursprüngliche Plugin, indem er dieses Plugin weiter erbt.

Durch Vorbereiten einer call- Funktion können Sie sie wie eine Funktion ausführen.

Verwenden Sie getattr, wenn Sie __call__ aufrufen. Dies führt dazu, dass die Bibliotheksseite die Plugin-Instanz im Lauf ausführt und die Bibliotheksinformationen zu diesem Zeitpunkt weitergibt. Dann ist die Plugin-Instanz getattr, die die Funktion herausbringt, die dem entsprechenden Hook "Start, Ende, Iteration" im Lauf entspricht, und sie verwendet.

Im Funktionslauf können Sie auch getattr wie call_plugins_start, call_plugins_finish löschen und alle Fälle separat schreiben. Auf diese Weise können Sie jedoch einheitlich schreiben.

Erweiterbarkeit der Bibliothek

Indem Sie eine Plug-In-Klasse zusammen mit der Bibliothek vorbereiten und an Benutzer verteilen

--Leiten Sie die Informationen in der Bibliothek von der Bibliotheksseite zum Plug-In weiter

Es gibt Vorteile. Beachten Sie jedoch, dass das Risiko von Laufzeitfehlern zunimmt, da Sie erst dann wissen, ob es korrekt ist, wenn Sie es ausführen.

Recommended Posts

[Road to Intermediate Python] Geben Sie die Ausführungsmethode dynamisch anhand des Variablennamens an
Ein Weg zum mittleren Python
[Road to Intermediate] Grundlegendes zu Python-Eigenschaften
[Road to Intermediate Python] Verwenden Sie ternäre Operatoren
[Road to Intermediate Python] Verwenden Sie Lambda-Ausdrücke
[Road to Intermediate Python] Zusammenfassung der Artikelverknüpfungen
Dynamisches Ersetzen der nächsten Methode in Python
[Road to Intermediate] Python scheint alles Objekte zu sein
So erhalten Sie den Variablennamen selbst in Python
[Road to Intermediate Python] Definieren Sie die Funktion __getattr__ in der Klasse
[Road to Intermediate Python] Definieren Sie in Ihrer eigenen Klasse
[Road to Intermediate Python] Installieren Sie Pakete in großen Mengen mit pip
[Python] So legen Sie Variablennamen dynamisch fest und vergleichen die Geschwindigkeit
[Road to Intermediate Python] Verwenden Sie die if-Anweisung in der Listeneinschlussnotation
[Road to Intermediate Python] Aktiviert Vergleichsoperationen mit Originalklassen
So überschreiben Sie eine benutzerdefinierte Typmethode, die von Python Swig generiert wird
[Road to Intermediate Python] Rufen Sie eine Klasseninstanz wie eine Funktion mit __call__ auf
Ausführung durch Subshell (und Variablenaktualisierung)
[Python] Weg zur Serpent (3) Python-Klasse
Weg zu Intermediate Linux: Network Edition
Python (vom ersten Mal bis zur Ausführung)