Implémentation d'une interface en Python – Real Python

By | février 10, 2020

Formation gratuite Python

Les interfaces jouent un rôle important en génie logiciel. À mesure qu'une application se développe, les mises à jour et les modifications apportées à la base de code deviennent plus difficiles à gérer. Plus souvent qu'autrement, vous vous retrouvez avec des cours qui se ressemblent beaucoup mais qui ne sont pas liés, ce qui peut entraîner une certaine confusion. Dans ce didacticiel, vous verrez comment utiliser un Interface Python pour aider à déterminer quelle classe vous devez utiliser pour résoudre le problème actuel.

Dans ce didacticiel, vous pourrez:

  • Comprendre comment les interfaces fonctionnent et les mises en garde de la création d'interface Python
  • Comprendre l'utilité des interfaces dans un langage dynamique comme Python
  • Mettre en place une interface informelle Python
  • Utilisation abc.ABCMeta et @ abc.abstractmethod pour implémenter une interface formelle Python

Les interfaces en Python sont gérées différemment de la plupart des autres langages et leur complexité de conception peut varier. À la fin de ce didacticiel, vous aurez une meilleure compréhension de certains aspects du modèle de données Python, ainsi que de la façon dont les interfaces en Python se comparent à celles des langages tels que Java, C ++ et Go.

Présentation de l'interface Python

À un niveau élevé, une interface agit comme un plan pour concevoir des cours. Comme les classes, les interfaces définissent des méthodes. Contrairement aux classes, ces méthodes sont abstraites. Un méthode abstraite est celui que l'interface définit simplement. Il n'implémente pas les méthodes. Cela se fait par classes, qui mettre en place l'interface et donner un sens concret aux méthodes abstraites de l'interface.

L'approche de Python pour la conception d'interfaces est quelque peu différente par rapport à des langages tels que Java, Go et C ++. Ces langues ont toutes un interface mot-clé, contrairement à Python. Python s'écarte en outre des autres langages sous un autre aspect. Il n’exige pas que la classe qui implémente l’interface définisse toutes les méthodes abstraites de l’interface.

Interfaces informelles

Dans certaines circonstances, vous n'aurez peut-être pas besoin des règles strictes d'une interface Python formelle. La nature dynamique de Python vous permet de mettre en œuvre un interface informelle. Une interface Python informelle est une classe qui définit des méthodes qui peuvent être remplacées, mais il n'y a pas d'application stricte.

Dans l'exemple suivant, vous prendrez le point de vue d'un ingénieur de données qui doit extraire du texte de différents types de fichiers non structurés, tels que des PDF et des e-mails. Vous allez créer une interface informelle qui définit les méthodes qui figureront à la fois dans PdfParser et EmlParser cours concrets:

classe InformalParserInterface:
    def load_data_source(soi, chemin: str, nom de fichier: str) -> str:
        "" "Charger le fichier pour extraire le texte." ""
        passer

    def extract_text(soi, nom_fichier complet: str) -> dicter:
        "" "Extraire le texte du fichier actuellement chargé." ""
        passer

InformalParserInterface définit les deux méthodes .load_data_source () et .extract_text (). Ces méthodes sont définies mais non implémentées. L'implémentation aura lieu une fois que vous aurez créé classes de béton qui héritent de InformalParserInterface.

Comme vous pouvez le voir, InformalParserInterface semble identique à une classe Python standard. Vous comptez sur la saisie de canard pour informer les utilisateurs qu'il s'agit d'une interface et doit être utilisée en conséquence.

Avec la saisie de canard à l'esprit, vous définissez deux classes qui implémentent le InformalParserInterface. Pour utiliser votre interface, vous devez créer une classe concrète. UNE classe de béton est une sous-classe de l'interface qui fournit une implémentation des méthodes de l'interface. Vous allez créer deux classes concrètes pour implémenter votre interface. Le premier est PdfParser, que vous utiliserez pour analyser le texte des fichiers PDF:

classe PdfParser(InformalParserInterface):
    "" "Extraire le texte d'un PDF" ""
    def load_data_source(soi, chemin: str, nom de fichier: str) -> str:
        "" "remplace InformalParserInterface.load_data_source" ""
        passer

    def extract_text(soi, full_file_path: str) -> dicter:
        "" "Remplace InformalParserInterface.extract_text" ""
        passer

La mise en œuvre concrète de InformalParserInterface vous permet désormais d'extraire du texte à partir de fichiers PDF.

La deuxième classe concrète est EmlParser, que vous utiliserez pour analyser le texte des e-mails:

classe EmlParser(InformalParserInterface):
    "" "Extraire le texte d'un e-mail" ""
    def load_data_source(soi, chemin: str, nom de fichier: str) -> str:
        "" "remplace InformalParserInterface.load_data_source" ""
        passer

    def extract_text_from_email(soi, full_file_path: str) -> dicter:
        "" "Une méthode définie uniquement dans EmlParser.
                                Ne remplace pas InformalParserInterface.extract_text
                                "" "
        passer

La mise en œuvre concrète de InformalParserInterface vous permet désormais d'extraire du texte à partir de fichiers e-mail.

Jusqu'à présent, vous en avez défini deux implémentations concrètes du InformalPythonInterface. Notez cependant que EmlParser ne parvient pas à définir correctement .extract_text (). Si vous deviez vérifier si EmlParser met en oeuvre InformalParserInterface, vous obtiendrez alors le résultat suivant:

# Vérifiez si PdfParser et EmlParser implémentent InformalParserInterface
issubclass(PdfParser, InformalParserInterface)   # Vrai
issubclass(EmlParser, InformalParserInterface)   # Vrai

Cela reviendrait Vrai, ce qui pose un peu de problème car il viole la définition d'une interface!

Maintenant, vérifiez le ordre de résolution de méthode (MRO) de PdfParser et EmlParser. Cela vous indique les superclasses de la classe en question, ainsi que l'ordre dans lequel elles sont recherchées pour exécuter une méthode. Vous pouvez afficher le MRO d'une classe à l'aide de la méthode dunder cls .__ mro__:

# (__main __. PdfParser, __main __. InformalParserInterface, objet)
PdfParser.__mro__

# (__main __. EmlParser, __main __. InformalParserInterface, objet)
EmlParser.__mro__

De telles interfaces informelles conviennent parfaitement aux petits projets où seuls quelques développeurs travaillent sur le code source. Cependant, à mesure que les projets s'agrandissent et que les équipes s'agrandissent, les développeurs peuvent passer d'innombrables heures à rechercher des erreurs logiques difficiles à trouver dans la base de code!

Utilisation de métaclasses

Idéalement, vous voudriez issubclass (EmlParser, InformalParserInterface rendre Faux lorsque la classe d'implémentation ne définit pas toutes les méthodes abstraites de l'interface. Pour ce faire, vous allez créer une métaclasse appelée ParserMeta. Vous allez remplacer deux méthodes de dunder:

  1. __instancecheck__
  2. __sousclasscheck__

Dans le bloc de code ci-dessous, vous créez une classe appelée UpdatedInformalParserInterface qui se construit à partir de la ParserMeta métaclasse:

classe ParserMeta(type):
    "" "Une métaclasse analyseur qui sera utilisée pour la création de la classe analyseur.
                "" "
    def __instancecheck__(cls, exemple):
        revenir cls.__sousclasscheck__(type(exemple))

    def __sousclasscheck__(cls, sous-classe):
        revenir (hasattr(sous-classe, 'load_data_source') et 
                appelable(sous-classe.load_data_source) et 
                hasattr(sous-classe, 'extract_text') et 
                appelable(sous-classe.extract_text))

classe UpdatedInformalParserInterface(métaclasse=ParserMeta):
    "" "Cette interface est utilisée pour les classes concrètes dont il faut hériter.
                Il n'est pas nécessaire de définir les méthodes ParserMeta comme n'importe quelle classe
                car ils sont implicitement mis à disposition via __subclasscheck__.
                "" "
    passer

Maintenant que ParserMeta et UpdatedInformalParserInterface ont été créés, vous pouvez créer vos implémentations concrètes.

Tout d'abord, créez une nouvelle classe d'analyse des fichiers PDF appelée PdfParserNew:

classe PdfParserNew:
    "" "Extraire le texte d'un PDF." ""
    def load_data_source(soi, chemin: str, nom de fichier: str) -> str:
        "" "remplace InformalParserInterface.load_data_source" ""
        passer

    def extract_text(soi, full_file_path: str) -> dicter:
        "" "Remplace InformalParserInterface.extract_text" ""
        passer

Ici, PdfParserNew remplace .load_data_source () et .extract_text (), donc issubclass (PdfParserNew, UpdatedInformalParserInterface) devrait revenir Vrai.

Dans ce bloc de code suivant, vous avez une nouvelle implémentation de l'analyseur de messagerie appelé EmlParserNew:

classe EmlParserNew:
    "" "Extraire le texte d'un e-mail." ""
    def load_data_source(soi, chemin: str, nom de fichier: str) -> str:
        "" "remplace InformalParserInterface.load_data_source" ""
        passer

    def extract_text_from_email(soi, full_file_path: str) -> dicter:
        "" "Une méthode définie uniquement dans EmlParser.
                                Ne remplace pas InformalParserInterface.extract_text
                                "" "
        passer

Ici, vous avez une métaclasse qui sert à créer UpdatedInformalParserInterface. En utilisant une métaclasse, vous n'avez pas besoin de définir explicitement les sous-classes. Au lieu de cela, la sous-classe doit définir les méthodes requises. Si ce n'est pas le cas, alors issubclass (EmlParserNew, UpdatedInformalParserInterface) renverra False.

Fonctionnement issubclass () sur vos classes concrètes produira ce qui suit:

issubclass(PdfParserNew, UpdatedInformalParserInterface) # Vrai
issubclass(EmlParserNew, UpdatedInformalParserInterface) # Faux

Comme prévu, EmlParserNew n'est pas une sous-classe de UpdatedInformalParserInterface puisque .extract_text () n’était pas défini dans EmlParserNew.

Voyons maintenant le MRO:

PdfParserNew.__mro__ # (, )

Comme vous pouvez le voir, UpdatedInformalParserInterface est une superclasse de PdfParserNew, mais il n'apparaît pas dans le MRO. Ce comportement inhabituel est dû au fait que UpdatedInformalParserInterface est un classe de base virtuelle de PdfParserNew.

Utilisation de classes de base virtuelles

Dans l'exemple précédent, issubclass (EmlParserNew, UpdatedInformalParserInterface) retourné True, même si UpdatedInformalParserInterface n'apparaissait pas dans le EmlParserNew MRO. C'est parce que UpdatedInformalParserInterface est un classe de base virtuelle de EmlParserNew.

La principale différence entre ces sous-classes et les sous-classes standard est que les classes de base virtuelles utilisent le __sousclasscheck__ méthode dunder pour vérifier implicitement si une classe est une sous-classe virtuelle de la superclasse. De plus, les classes de base virtuelles n'apparaissent pas dans la sous-classe MRO.

Jetez un oeil à ce bloc de code:

classe PersonMeta(type):
    "" "Une métaclasse de personne" ""
    def __instancecheck__(cls, exemple):
        revenir cls.__sousclasscheck__(type(exemple))

    def __sousclasscheck__(cls, sous-classe):
        revenir (hasattr(sous-classe, 'Nom') et 
                appelable(sous-classe.Nom) et 
                hasattr(sous-classe, 'âge') et 
                appelable(sous-classe.âge))

classe PersonSuper:
    "" "Une superclasse" ""
    def get_name(soi) -> str:
        passer

    def get_age(soi) -> int:
        passer

classe La personne(métaclasse=PersonMeta):
    "" "Interface Personne construite à partir de la métaclasse PersonMeta." ""
    passer

Ici, vous avez la configuration pour créer vos classes de base virtuelles:

  1. La métaclasse PersonMeta
  2. La classe de base PersonSuper
  3. L'interface Python La personne

Maintenant que la configuration pour créer classes de base virtuelles vous avez défini deux classes concrètes, Employé et Un ami. le Employé hérite de la classe PersonSuper, tandis que Un ami hérite implicitement de La personne:

# Hériter de sous-classes
classe Employé(PersonSuper):
    "" "Hérite de PersonSuper
                PersonSuper apparaîtra dans Employee .__ mro__
                "" "
    passer

classe Un ami:
    "" "Construit implicitement à partir de Person
                Friend est une sous-classe virtuelle de Person depuis
                les deux méthodes requises existent.
                Personne hors ami .__ mro__
                "" "
    def Nom(soi):
        passer

    def âge(soi):
        passer

Bien que Un ami n'hérite pas explicitement de La personne, il implémente .Nom() et .âge(), donc La personne devient un classe de base virtuelle de Un ami. Quand tu cours issubclass (ami, personne) il devrait revenir Vrai, qui veut dire Un ami est une sous-classe de La personne.

Le suivant UML le diagramme montre ce qui se passe lorsque vous appelez issubclass () sur le Un ami classe:

classe de base virtuelle

Jetez un oeil à PersonMeta, vous remarquerez qu'il existe une autre méthode de dunder appelée __instancecheck__. Cette méthode est utilisée pour vérifier si des instances de Un ami sont créés à partir du La personne interface. Votre code appellera __instancecheck__ quand vous utilisez isinstance (ami, personne).

Interfaces formelles

Les interfaces informelles peuvent être utiles pour les projets avec une petite base de code et un nombre limité de programmeurs. Cependant, les interfaces informelles ne seraient pas la bonne approche pour les applications plus importantes. Afin de créer un interface formelle Python, vous aurez besoin de quelques autres outils de Python abc module.

En utilisant abc.ABCMeta

Pour appliquer l'instanciation de sous-classe des méthodes abstraites, vous utiliserez la fonction intégrée de Python ABCMeta du abc module. Revenons à votre UpdatedInformalParserInterface interface, vous avez créé votre propre métaclasse, ParserMeta, avec les méthodes de dunder surchargées __instancecheck__ et __sousclasscheck__.

Plutôt que de créer votre propre métaclasse, vous utiliserez abc.ABCMeta comme métaclasse. Ensuite, vous écraserez sous-classe au lieu de __instancecheck_ et __sousclasscheck__, car il crée une mise en œuvre plus fiable de ces méthodes de dunder.

En utilisant __sous-classehook__

Voici l'implémentation de FormalParserInterface en utilisant abc.ABCMeta comme métaclasse:

importation abc

classe FormalParserInterface(métaclasse=abc.ABCMeta):
    @classmethod
    def __sous-classehook__(cls, sous-classe):
        revenir (hasattr(sous-classe, 'load_data_source') et 
                appelable(sous-classe.load_data_source) et 
                hasattr(sous-classe, 'extract_text') et 
                appelable(sous-classe.extract_text))

classe PdfParserNew:
    "" "Extraire le texte d'un PDF." ""
    def load_data_source(soi, chemin: str, nom de fichier: str) -> str:
        "" "remplace InformalParserInterface.load_data_source" ""
        passer

    def extract_text(soi, full_file_path: str) -> dicter:
        "" "Remplace InformalParserInterface.extract_text" ""
        passer

classe EmlParserNew:
    "" "Extraire le texte d'un e-mail." ""
    def load_data_source(soi, chemin: str, nom de fichier: str) -> str:
        "" "remplace InformalParserInterface.load_data_source" ""
        passer

    def extract_text_from_email(soi, full_file_path: str) -> dicter:
        "" "Une méthode définie uniquement dans EmlParser.
                                Ne remplace pas InformalParserInterface.extract_text
                                "" "
        passer

Si vous courez issubclass () sur PdfParserNew et EmlParserNew, puis issubclass reviendra Vrai et Faux, respectivement.

En utilisant abc enregistrer une sous-classe virtuelle

Une fois que vous avez importé le abc module, vous pouvez directement enregistrer une sous-classe virtuelle en utilisant le .S'inscrire() métaméthode. Dans l'exemple suivant, vous enregistrez l'interface Double en tant que classe de base virtuelle du intégré __flotte__ classe:

classe Double(métaclasse=abc.ABCMeta):
    "" "Nombre à virgule flottante double précision." ""
    passer

Double.S'inscrire(flotte)
impression(issubclass(flotte, Double))    # Vrai
impression(isinstance(1,2345, Double))   # Vrai

En utilisant le .S'inscrire() méta méthode, vous vous êtes enregistré avec succès Double comme une sous-classe virtuelle de flotte.

Une fois inscrit Double, vous pouvez l'utiliser comme décorateur de classe pour définir la classe décorée comme une sous-classe virtuelle:

@Double.S'inscrire
classe Double64:
    "" "Un nombre à virgule flottante double précision 64 bits." ""
    passer

impression(issubclass(Double64, Double))   # Vrai

La méthode de registre du décorateur vous aide à créer une hiérarchie d'héritage de classe virtuelle personnalisée.

Utilisation de la détection de sous-classe avec enregistrement

Vous devez être prudent lorsque vous combinez __sous-classehook__ avec .S'inscrire(), comme __sous-classehook__ a priorité sur l'enregistrement de sous-classe virtuelle. Pour vous assurer que les sous-classes virtuelles enregistrées sont prises en compte, vous devez ajouter Pas mis en œuvre à la __sous-classehook__ méthode de dunder. le FormalParserInterface serait mis à jour comme suit:

classe FormalParserInterface(métaclasse=abc.ABCMeta):
    @classmethod
    def __sous-classehook__(cls, sous-classe):
        revenir (hasattr(sous-classe, 'load_data_source') et 
                appelable(sous-classe.load_data_source) et 
                hasattr(sous-classe, 'extract_text') et 
                appelable(sous-classe.extract_text) ou 
                Pas mis en œuvre)

classe PdfParserNew:
    "" "Extraire le texte d'un PDF." ""
    def load_data_source(soi, chemin: str, nom de fichier: str) -> str:
        "" "remplace InformalParserInterface.load_data_source" ""
        passer

    def extract_text(soi, full_file_path: str) -> dicter:
        "" "Remplace InformalParserInterface.extract_text" ""
        passer

@FormalParserInterface.S'inscrire
classe EmlParserNew:
    "" "Extraire le texte d'un e-mail." ""
    def load_data_source(soi, chemin: str, nom de fichier: str) -> str:
        "" "remplace InformalParserInterface.load_data_source" ""
        passer

    def extract_text_from_email(soi, full_file_path: str) -> dicter:
        "" "Une méthode définie uniquement dans EmlParser.
                                Ne remplace pas InformalParserInterface.extract_text
                                "" "
        passer

impression(issubclass(PdfParserNew, FormalParserInterface))  # Vrai
impression(issubclass(EmlParserNew, FormalParserInterface))  # Vrai

Puisque vous avez utilisé l'enregistrement, vous pouvez voir que EmlParserNew est considéré comme une sous-classe virtuelle de votre FormalParserInterface interface. Ce n'est pas ce que tu voulais depuis EmlParserNew ne remplace pas .extract_text (). Veuillez faire preuve de prudence lors de l'enregistrement d'une sous-classe virtuelle!

Utilisation de la déclaration de méthode abstraite

Un méthode abstraite est une méthode déclarée par l'interface Python, mais elle peut ne pas avoir d'implémentation utile. La méthode abstraite doit être remplacée par la classe concrète qui implémente l'interface en question.

Pour créer des méthodes abstraites en Python, vous ajoutez le @ abc.abstractmethod décorateur aux méthodes de l'interface. Dans l'exemple suivant, vous mettez à jour le FormalParserInterface d'inclure les méthodes abstraites .load_data_source () et .extract_text ():

classe FormalParserInterface(métaclasse=abc.ABCMeta):
    @classmethod
    def __sous-classehook__(cls, sous-classe):
        revenir (hasattr(sous-classe, 'load_data_source') et 
                appelable(sous-classe.load_data_source) et 
                hasattr(sous-classe, 'extract_text') et 
                appelable(sous-classe.extract_text) ou 
                Pas mis en œuvre)

    @abc.méthode abstraite
    def load_data_source(soi, chemin: str, nom de fichier: str):
        "" "Charger dans l'ensemble de données" ""
        élever NotImplementedError

    @abc.méthode abstraite
    def extract_text(soi, full_file_path: str):
        "" "Extraire le texte de l'ensemble de données" ""
        élever NotImplementedError

classe PdfParserNew(FormalParserInterface):
    "" "Extraire le texte d'un PDF." ""
    def load_data_source(soi, chemin: str, nom de fichier: str) -> str:
        "" "remplace InformalParserInterface.load_data_source" ""
        passer

    def extract_text(soi, full_file_path: str) -> dicter:
        "" "Remplace InformalParserInterface.extract_text" ""
        passer

classe EmlParserNew(FormalParserInterface):
    "" "Extraire le texte d'un e-mail." ""
    def load_data_source(soi, chemin: str, nom de fichier: str) -> str:
        "" "remplace InformalParserInterface.load_data_source" ""
        passer

    def extract_text_from_email(soi, full_file_path: str) -> dicter:
        "" "Une méthode définie uniquement dans EmlParser.
                                Ne remplace pas InformalParserInterface.extract_text
                                "" "
        passer

pdf_parser = PdfParserNew() # Ne provoquera aucune erreur
eml_parser = EmlParserNew() # Générera une erreur

Dans l'exemple ci-dessus, vous avez finalement créé une interface formelle qui génère des erreurs lorsque les méthodes abstraites ne sont pas remplacées. le PdfParserNew exemple, pdf_parser, ne générera aucune erreur, car PdfParserNew remplace correctement le FormalParserInterface méthodes abstraites. cependant, EmlParserNew générera l'erreur suivante:

Traceback (plus récent appel dernier):
  Fichier "real_python_interfaces.py", ligne 53, dans <module>
    eml_interface = EmlParserNew()
Erreur-type: Pouvez'instanciez pas la classe abstraite EmlParserNew avec les méthodes abstraites extract_text

Comme vous pouvez le voir, le message de trace vous indique que vous n'avez pas remplacé toutes les méthodes abstraites. C'est le comportement que vous attendez lors de la construction d'une interface Python formelle.

Interfaces dans d'autres langues

Les interfaces apparaissent dans de nombreux langages de programmation et leur implémentation varie considérablement d'un langage à l'autre. Dans les sections suivantes, vous comparerez des interfaces en Python à Java, C ++ et Go.

Java

Contrairement à Python, Java contient un interface mot-clé. En gardant l'exemple de l'analyseur de fichiers, vous déclarez une interface en Java comme ceci:

Publique interface FileParserInterface 
    // Les champs statiques et les méthodes abstraites vont ici ...

Vous allez maintenant créer deux classes concrètes, PdfParser et EmlParser, pour mettre en œuvre FileParserInterface. Pour ce faire, vous devez utiliser le met en oeuvre mot-clé dans la définition de classe, comme ceci:

Publique classe EmlParser met en oeuvre FileParserInterface 
     Publique néant loadDataSource() 
            // Code pour charger l'ensemble de données
        

     Publique néant extractText() 
            // Code pour extraire le texte
        

En poursuivant avec votre exemple d'analyse de fichiers, une interface Java entièrement fonctionnelle ressemblerait à ceci:

importation java.util. *;
importation java.io. *;

Publique classe FileParser 
    Publique statique néant principale(Chaîne[] args) jette IOException 

        Système.en dehors.println("Bonjour le monde!");

    

    Publique interface FileParserInterface 
        HashMap<Chaîne, Liste des tableaux<Chaîne>> file_contents = nul;

        Publique néant loadDataSource();

        Publique néant extractText();
    

    Publique classe PdfParser met en oeuvre FileParserInterface 
        Publique néant loadDataSource() 
            // Code pour charger l'ensemble de données
        

        Publique néant extractText() 
            // Code pour extraire le texte
        

    

    Publique classe EmlParser met en oeuvre FileParserInterface 
        Publique néant loadDataSource() 
            // Code pour charger l'ensemble de données
        

        Publique néant extractText() 
            // Code pour extraire le texte
        
    


Comme vous pouvez le voir, une interface Python vous offre beaucoup plus de flexibilité lors de la création qu'une interface Java.

C ++

Comme Python, C ++ utilise des classes de base abstraites pour créer des interfaces. Lors de la définition d'une interface en C ++, vous utilisez le mot clé virtuel pour décrire une méthode qui devrait être écrasée dans la classe concrète:

classe FileParserInterface 

    Publique:
        virtuel néant loadDataSource(std::chaîne chemin, std::chaîne nom de fichier);
        virtuel néant extractText(std::chaîne nom_fichier complet);
;

Lorsque vous souhaitez implémenter l'interface, vous donnez le nom de classe concret, suivi de deux points (:), puis le nom de l'interface. L'exemple suivant illustre l'implémentation de l'interface C ++:

classe PdfParser : FileParserInterface 
    Publique:
        néant loadDataSource(std::chaîne chemin, std::chaîne nom de fichier);
        néant extractText(std::chaîne nom_fichier complet);
;

classe EmlParser : FileParserInterface 
    Publique:
        néant loadDataSource(std::chaîne chemin, std::chaîne nom de fichier);
        néant extractText(std::chaîne nom_fichier complet);
;

Une interface Python et une interface C ++ présentent certaines similitudes en ce qu'elles utilisent toutes deux des classes de base abstraites pour simuler des interfaces.

Aller

Bien que la syntaxe de Go rappelle Python, le langage de programmation Go contient un interface mot-clé, comme Java. Créons le fileParserInterface dans Go:

type fileParserInterface interface 
        loadDataSet(chemin chaîne, nom de fichier chaîne)
        extractText(full_file_path chaîne)

Une grande différence entre Python et Go est que Go n'a pas de classes. Au contraire, Go est similaire à C en ce qu'il utilise le struct mot-clé pour créer des structures. UNE structure est similaire à une classe dans la mesure où une structure contient des données et des méthodes. Cependant, contrairement à une classe, toutes les données et méthodes sont accessibles au public. Les structures concrètes de Go seront utilisées pour mettre en œuvre fileParserInterface.

Voici un exemple de la façon dont Go utilise les interfaces:

paquet principale

importation (
        "fmt"
)

type fileParserInterface interface 
        loadDataSet(chemin chaîne, nom de fichier chaîne)
        extractText(full_file_path chaîne)


type pdfParser struct 
        // Les données vont ici ...


type emlParser struct 
        // Les données vont ici ...


func (p pdfParser) loadDataSet() 
        // Définition de la méthode ...


func (p pdfParser) extractText() 
        // Définition de la méthode ...


func (e emlParser) loadDataSet() 
        // Définition de la méthode ...


func (e emlParser) extractText() 
        // Définition de la méthode ...


func principale() 
        fmt.Printf("Bonjour le monde!")

Contrairement à une interface Python, une interface Go est créée à l'aide de structures et du mot clé explicite interface.

Conclusion

Python offre une grande flexibilité lorsque vous créez des interfaces. Une interface Python informelle est utile pour les petits projets où vous êtes moins susceptible de vous tromper quant aux types de retour des méthodes. À mesure qu’un projet se développe, la nécessité interface formelle Python devient plus important car il devient plus difficile de déduire les types de retour. Cela garantit que la classe concrète, qui implémente l'interface, écrase les méthodes abstraites.

Maintenant vous pouvez:

  • Comprendre comment fonctionnent les interfaces et les mises en garde de la création d'une interface Python
  • Comprendre le utilité des interfaces dans un langage dynamique comme Python
  • Mettre en place formel et informel interfaces en Python
  • Comparer les interfaces Python à ceux des langages comme Java, C ++ et Go

Maintenant que vous vous êtes familiarisé avec la façon de créer une interface Python, ajoutez une interface Python à votre prochain projet pour voir son utilité en action!