Ist es überhaupt möglich, das Gesetz der Abhängigkeitsumkehr (DIP) in Python zu realisieren?

Einführung

Ich habe mir heutzutage viel Sorgen um Design und Architektur gemacht, aber ich habe meine eigene Meinung darüber geschrieben, ob Python, eine dynamisch typisierte Sprache, auch das Gesetz der Abhängigkeitsumkehr implementieren kann. Meine Meinung ist nicht absolut richtig, aber ich hoffe es hilft.

Was ist Polymorphismus?

Zuerst müssen wir den ** Polymorphismus ** verstehen, bevor wir das Gesetz der Abhängigkeitsumkehr verstehen können. Die Erklärung stammt aus Wikipedia.

Polymorphismus beschreibt die Art des Typsystems einer Programmiersprache und gehört für jedes Element der Programmiersprache (Konstanten, Variablen, Ausdrücke, Objekte, Funktionen, Methoden usw.) mehreren Typen an. Bezieht sich auf das Eigentum der Vergebung. Auch Polymorphismus, Polymorphismus, Polymorphismus, Diversität genannt.

Da der Inhalt schwer zu verstehen ist, werde ich ihn ausführlich erläutern. Die Essenz ist der Teil von "** bezieht sich auf die Eigenschaft, dass sie mehreren Typen angehören dürfen **". Bei einer dynamisch typisierten Sprache wie Python ist sie nicht so bewusst, aber bei einer statisch typisierten Sprache darf sie grundsätzlich nicht zu mehreren Typen gehören, da die Variablentypen begrenzt sind.

Siehe zum Beispiel das folgende Beispiel. (C ++ - Code, aber ich denke nicht, dass der Inhalt schwierig ist)

main.cpp


#include <iostream>
using namespace std;

int main()
{
    int a = 1;
    string b = "hello";
    a = b; // error
}

Die Variable a wird durch int definiert, und die Variable b wird durch einen String definiert. Ich versuche, einer Variablen vom Typ int eine Zeichenfolgentypvariable b mit "a = b" zuzuweisen. Dieser Vorgang führt zu einem Fehler. Dies liegt daran, dass ** Variable a als int-Typ definiert ist und nicht zu mehr als einem Typ gehören kann **.

Mit anderen Worten, Variablen usw. können grundsätzlich nicht zu mehreren Typen gehören. Im Fall von Polymorphismus wird der Inhalt, der es ihm ermöglicht, zu mehreren Typen zu gehören, im zitierten Teil von Wikipedia erläutert.

Schauen wir uns ein Beispiel für Polymorphismus an. (C ++ - Code, aber Sie müssen den Code selbst nicht verstehen)

main.cpp


#include <iostream>
using namespace std;

class Human{
    public:
        string name;
        int age;
        Human(const string _name, const int _age){
            name = _name;
            age = _age;
        };
        virtual void print_gender(){};
        void print_info(){
            cout << "name: " << name << ", age: " << age << endl;
        };
};

class Man: public Human{
    public:
        Man(const string _name, const int _age): Human(_name,_age){};
        void print_gender() override {
            cout << "I am man." << endl;
        };
};

class Woman: public Human{
    public:
        Woman(const string _name, const int _age): Human(_name,_age){};
        void print_gender() override {
            cout << "I am woman." << endl;
        };
};

int main()
{
    Man* taro = new Man("taro", 12);
    Woman* hanako = new Woman("hanako", 23);
    Human* human = taro;
    human->print_gender();
    human->print_info();
}

Die wichtigen Teile sind wie folgt.

    Man* taro = new Man("taro", 12);
    Woman* hanako = new Woman("hanako", 23);
    Human* human = taro;

Eine Variable namens Taro der Man-Klasse wird der in der Human-Klasse definierten Variablen Human zugewiesen. Ich habe in der obigen Erklärung erwähnt, dass Variablen nur zu einem Typ (Klasse) gehören können, aber die Variable Mensch scheint sowohl zur Klasse Mensch als auch zur Klasse Mensch zu gehören. (Genau genommen gehört es nur dem Menschen)

Der Grund, warum dies möglich ist, ist, dass die Man-Klasse eine abgeleitete Klasse der Human-Klasse ist. Die Man-Klasse und die Human-Klasse sind verwandt. Das Bild ist also, dass Sie zulassen, dass verwandte Dinge auf die gleiche Weise behandelt werden.

Ich denke, der Vorteil des Polymorphismus besteht darin, dass Sie sauberen Code schreiben können, weil Sie Dinge mit denselben Eigenschaften auf dieselbe Weise behandeln können. (Ich werde keine konkreten Beispiele erklären. Es tut mir leid.)

Über Abstraktion und Konkretheit

Als Vorwissen ist es notwendig, ein wenig über "abstrakt" und "konkret" zu verstehen. Ich werde ein wenig über die Worte erklären.

Was ist abstrakt

Abstract kann als Schnittstelle umformuliert werden, ist jedoch im Grunde eine Typdefinition (die möglicherweise nicht genau korrekt ist). Betrachten Sie beispielsweise die folgende Funktion.

main1.py


def add_number(a: int, b: int) -> int:
    """Gibt das Ergebnis des Hinzufügens von zwei Argumenten zurück"""
    return a + b

Eine Funktion namens add_number definiert eine Schnittstelle, die ein Argument von int verwendet und das Ergebnis von int ändert. Aus abstrakter Sicht denke ich nicht an das Innere der Implementierung, daher lautet der Funktionsname add_number, aber es ist mir egal, ob die Multiplikation anstelle der Addition innerhalb erfolgt. Berücksichtigen Sie nur die Ein- und Ausgänge (Schnittstellen).

Was ist konkret

Insbesondere denken wir über das Innere der Implementierung nach. Daher sollten wir prüfen, ob die interne Implementierung der Funktion add_number Addition oder Multiplikation ist.

Was ist das Gesetz der Abhängigkeitsumkehr?

Die Erklärung der vorausgesetzten Kenntnisse ist lang geworden. Außerdem gibt es fast keinen Python-Code ... Zuallererst ist die Bedeutung des Wortes "Abhängigkeit" verwirrend, deshalb werde ich es von dort aus erklären.

Siehe zum Beispiel den folgenden Code.

main2.py(Auszug)


def main():
    taro: Man = Man('taro', 12)
    taro.print_gender()
    taro.print_info()

Es scheint, dass Sie in der Hauptfunktion eine Klasse namens Man verwenden. Dieser Zustand kann als "die Hauptfunktion hängt von der Man-Klasse ab" bezeichnet werden. Mit anderen Worten, wenn der Inhalt der Man-Klasse geändert wird, kann auch die Hauptfunktion betroffen sein.

Lassen Sie uns nun die Erklärung des Gesetzes der Abhängigkeitsumkehr aus Wikipedia zitieren.

Im objektorientierten Design ist das Prinzip der Abhängigkeitsumkehr oder das Prinzip der Abhängigkeitsinversion 1 ein Begriff, der sich auf eine bestimmte Form bezieht, um Softwaremodule lose gekoppelt zu halten. Nach diesem Prinzip werden die traditionellen Abhängigkeiten von Modulen höherer Ebene zu Modulen niedrigerer Ebene, die das Softwareverhalten definieren, umgekehrt, sodass die Module höherer Ebene unabhängig von den Implementierungsdetails der Module niedrigerer Ebene gehalten werden können. Werden A. Module höherer Ebene sollten nicht von Modulen niedrigerer Ebene abhängen. Beide sollten sich auf Abstraktionen stützen. B. Abstracts sollten sich nicht auf Details stützen. Details sollten auf Abstraktion beruhen.

Eine andere esoterische Erklärung. .. .. Zuallererst die Wörter "oben" und "unten", aber im vorherigen Beispiel ist die Hauptfunktion die obere und die Man-Klasse die untere. Mit anderen Worten bedeutet "Module der oberen Ebene sollten nicht von Modulen der unteren Ebene abhängen", was speziell bedeutet, dass "die Hauptfunktion nicht von der Man-Klasse abhängen sollte". Als nächstes bedeutet der Teil, dass "beide von Abstraktionen abhängen sollten", mit anderen Worten, dass er eher von der Schnittstelle (Typ) als von der internen Implementierung abhängen sollte.

Es ist fast das gleiche wie der obige Code, aber siehe das folgende Beispiel.

main3.py(Auszug)


def main():
    taro: Human = Man('taro', 12)
    taro.print_gender()
    taro.print_info()

Der Unterschied besteht darin, dass die ** Hauptfunktion ihre Abhängigkeit von der Man-Klasse durch eine Abhängigkeit von der Human-Klasse ** ersetzt hat. Schauen wir uns nun die Implementierungen der Klassen Human und Man an. (Der Inhalt ist ein Auszug, der vollständige Text steht am Ende)

main3.py(Auszug)


@dataclass
class Human(metaclass=ABCMeta):
    name: str
    age: int

    #Abstrakte Methode
    @abstractmethod
    def print_gender(self) -> None:
        pass

    #Gängige Methode
    def print_info(self) -> None:
        print(f'name: {self.name}, age: {self.age}')

class Man(Human):
    def print_gender(self):
        print('I am man.')

Die Human-Klasse ist die Basisklasse und enthält keine komplexe Geschäftslogik. Mit anderen Worten, es kann eine abstrakte Klasse genannt werden. Im Gegenteil, die Man-Klasse ist eine konkrete Klasse, da es sich um eine Klasse handelt, die eine interne Implementierung enthält. Der Unterschied zwischen der Human-Klasse und der Man-Klasse besteht darin, dass sich die Human-Klasse weniger häufig und die Man-Klasse häufiger ändert. Der Grund ist natürlich, dass die Human-Klasse nur die Schnittstelle definiert (nicht genau, aber ...) und die Man-Klasse die interne Implementierung und Geschäftslogik enthält.

An dieser Stelle sehen Sie die Vorteile des Wechsels der Hauptfunktion von einer Man-Klasse (konkret) zu einer Human-Klasse (abstrakt). Wenn Sie von der Man-Klasse abhängig sind, wird die Hauptfunktion von den Änderungen in der Man-Klasse beeinflusst, sodass die Häufigkeit von Änderungen in der Man-Klasse hoch ist und daher stark beeinflusst wird. Im Gegenteil, wenn es von der menschlichen Klasse abhängt, wird es beeinflusst, wenn die menschliche Klasse geändert wird, aber es wird weniger betroffen sein, da die Änderungshäufigkeit geringer ist als die der Man-Klasse.

Wenn Sie sich also auf Abstraktionen verlassen, können Sie Code schreiben, der gegenüber Änderungen robuster ist.

Kann Python das Gesetz der Abhängigkeitsumkehr verwirklichen?

Sie können, aber es ist nicht perfekt. Insbesondere ist es möglich, die abstrakte Klasse abc, lint und type check tool zusammen zu verwenden. Im Fall von Python funktioniert das Programm selbst, selbst wenn die Typinformationen falsch sind, so dass es nicht möglich ist, das gleiche Niveau wie bei anderen statisch typisierten Sprachen zu erreichen. Wenn Sie ein höheres Niveau anstreben, kann dies meiner Meinung nach erreicht werden, indem Sie die Entwicklungsumgebung als Team gründlich ausrichten und den Typ und die Flusen durch Vorabbindung überprüfen. Ich denke, dass es Funktionen bietet, die für die praktische Anwendung kein Problem darstellen.

Schließlich

Ich habe es in Eile geschrieben, daher denke ich, dass es sehr leicht zu verstehen ist. Dieser Bereich ist schwer zu verstehen, daher hoffe ich, dass er so hilfreich wie möglich ist. Wenn Sie Fragen in den Kommentaren haben, werden wir so viel wie möglich beantworten. Es wäre hilfreich, wenn Sie auf Fehler oder Ratschläge hinweisen könnten.

Vollständiger Implementierungscode

main3.py


from abc import ABCMeta, abstractmethod
from dataclasses import dataclass

@dataclass
class Human(metaclass=ABCMeta):
    name: str
    age: int

    #Abstrakte Methode
    @abstractmethod
    def print_gender(self) -> None:
        pass

    #Gängige Methode
    def print_info(self) -> None:
        print(f'name: {self.name}, age: {self.age}')

class Man(Human):
    def print_gender(self):
        print('I am man.')

class Woman(Human):
    def print_gender(self):
        print('I am woman.')

def main():
    taro: Human = Man('taro', 12)
    taro.print_gender()
    taro.print_info()

Recommended Posts

Ist es überhaupt möglich, das Gesetz der Abhängigkeitsumkehr (DIP) in Python zu realisieren?
Implementieren Sie das Singleton-Muster in Python
Der erste Schritt von Python Matplotlib
Linux ist in erster Linie so etwas
Implementieren Sie XENO mit Python
Implementieren Sie die Lösung der Riccati-Algebra in Python
Implementieren Sie Traceroute in Python 3
Ich habe versucht, die Mail-Sendefunktion in Python zu implementieren
Finde Fehler in Python
Implementieren Sie Naive Bayes in Python 3.3
Implementieren Sie Redis Mutex in Python
Implementieren Sie die Erweiterung in Python
Implementieren Sie schnelles RPC in Python
Implementieren Sie den Dijkstra-Algorithmus in Python
Implementieren Sie den Slack Chat Bot in Python
DI (Dependency Injection) in Python
Spielen Sie, indem Sie die Riot Games-API in Python First Half drücken
Implementieren Sie das Stacking-Lernen in Python [Kaggle]
Implementieren Sie die Funktion power.prop.test von R in Python
Abrufen der arXiv-API in Python
Erster Python 3 ~ Der Beginn der Wiederholung ~
Python im Browser: Brythons Empfehlung
Speichern Sie die Binärdatei in Python
Klicken Sie in Python auf die Sesami-API
Holen Sie sich den Desktop-Pfad in Python
Holen Sie sich den Skriptpfad in Python
Im Python-Befehl zeigt Python auf Python3.8
Klicken Sie auf die Web-API in Python
Ich habe die Warteschlange in Python geschrieben
Berechnen Sie den Vormonat in Python
Untersuchen Sie die Klasse eines Objekts mit Python
Holen Sie sich den Desktop-Pfad in Python
Implementieren Sie die REST-API schnell in Python
Greifen Sie mit Python auf die Twitter-API zu
Ich habe den Stack in Python geschrieben
Beherrsche das schwache Ref-Modul in Python
Ein nützlicher Hinweis, wenn Sie Python nach langer Zeit verwenden
Bewegen Sie die Schildkröte an die Stelle, an der Sie mit der Maus mit der Schildkröte in Python klicken