Question Différence entre classe abstraite et interface en Python


Quelle est la différence entre classe abstraite et interface en Python?


439
2017-12-16 17:32


origine


Réponses:


Ce que vous verrez parfois est le suivant:

class Abstract1( object ):
    """Some description that tells you it's abstract,
    often listing the methods you're expected to supply."""
    def aMethod( self ):
        raise NotImplementedError( "Should have implemented this" )

Parce que Python n'a pas (et n'a pas besoin) un contrat d'interface formel, la distinction de style Java entre l'abstraction et l'interface n'existe pas. Si quelqu'un fait l'effort de définir une interface formelle, ce sera aussi une classe abstraite. Les seules différences seraient dans l'intention déclarée dans le docstring.

Et la différence entre abstract et interface est une chose qui coupe les cheveux lorsque vous tapez un canard.

Java utilise des interfaces car il ne possède pas d'héritage multiple.

Comme Python possède plusieurs héritages, vous pouvez également voir quelque chose comme ceci

class SomeAbstraction( object ):
    pass # lots of stuff - but missing something

class Mixin1( object ):
    def something( self ):
        pass # one implementation

class Mixin2( object ):
    def something( self ):
        pass # another

class Concrete1( SomeAbstraction, Mixin1 ):
    pass

class Concrete2( SomeAbstraction, Mixin2 ):
    pass

Cela utilise une sorte de super-classe abstraite avec des mixins pour créer des sous-classes concrètes qui sont disjointes.


507
2017-12-16 17:59



Quelle est la différence entre classe abstraite et interface en Python?

Une interface, pour un objet, est un ensemble de méthodes et d'attributs sur cet objet.

En Python, nous pouvons utiliser une classe de base abstraite pour définir et appliquer une interface.

Utilisation d'une classe de base abstraite

Par exemple, disons que nous voulons utiliser l’une des classes de base abstraites du collections module:

import collections
class MySet(collections.Set):
    pass

Si nous essayons de l'utiliser, nous obtenons un TypeError car la classe que nous avons créée ne supporte pas le comportement attendu des ensembles:

>>> MySet()
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: Can't instantiate abstract class MySet with abstract methods
__contains__, __iter__, __len__

Nous sommes donc tenus de mettre en œuvre à moins  __contains__, __iter__, et __len__. Utilisons cet exemple de mise en œuvre de la Documentation:

class ListBasedSet(collections.Set):
    """Alternate set implementation favoring space over speed
    and not requiring the set elements to be hashable. 
    """
    def __init__(self, iterable):
        self.elements = lst = []
        for value in iterable:
            if value not in lst:
                lst.append(value)
    def __iter__(self):
        return iter(self.elements)
    def __contains__(self, value):
        return value in self.elements
    def __len__(self):
        return len(self.elements)

s1 = ListBasedSet('abcdef')
s2 = ListBasedSet('defghi')
overlap = s1 & s2

Implémentation: Création d'une classe de base abstraite

Nous pouvons créer notre propre classe de base abstraite en définissant la métaclasse sur abc.ABCMeta et en utilisant le abc.abstractmethod décorateur sur les méthodes pertinentes. La métaclasse sera ajouter les fonctions décorées à la __abstractmethods__ attribut, empêchant l'instanciation jusqu'à ce qu'ils soient définis.

import abc

Par exemple, "effable" est défini comme quelque chose qui peut être exprimé en mots. Supposons que nous voulions définir une classe de base abstraite qui soit effaçable, en Python 2:

class Effable(object):
    __metaclass__ = abc.ABCMeta
    @abc.abstractmethod
    def __str__(self):
        raise NotImplementedError('users must define __str__ to use this base class')

Ou dans Python 3, avec la légère modification de la déclaration de métaclasse:

class Effable(object, metaclass=abc.ABCMeta):
    @abc.abstractmethod
    def __str__(self):
        raise NotImplementedError('users must define __str__ to use this base class')

Maintenant, si nous essayons de créer un objet effable sans implémenter l'interface:

class MyEffable(Effable): 
    pass

et essayez de l'instancier:

>>> MyEffable()
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: Can't instantiate abstract class MyEffable with abstract methods __str__

On nous dit que nous n'avons pas fini le travail.

Maintenant, si nous nous conformons en fournissant l'interface attendue:

class MyEffable(Effable): 
    def __str__(self):
        return 'expressable!'

nous pouvons alors utiliser la version concrète de la classe dérivée de la classe abstraite:

>>> me = MyEffable()
>>> print(me)
expressable!

Il y a d'autres choses que nous pourrions faire avec cela, comme enregistrer des sous-classes virtuelles qui implémentent déjà ces interfaces, mais je pense que cela dépasse la portée de cette question. Les autres méthodes démontrées ici devraient adapter cette méthode en utilisant abc module pour le faire, cependant.

Conclusion

Nous avons démontré que la création d'une classe de base abstraite définit des interfaces pour les objets personnalisés en Python.


131
2017-07-15 19:15



Python> = 2.6 a Classes de base abstraites.

Classes de base abstraites (en abrégé   ABCs) complètent le typage du canard par   fournir un moyen de définir des interfaces   quand d'autres techniques comme hasattr ()   serait maladroit. Python est livré avec   de nombreux ABC intégrés pour les structures de données   (dans le module des collections), les chiffres   (dans le module des nombres), et les flux   (dans le module io). Vous pouvez créer   votre propre ABC avec le module abc.

Il y a aussi Interface Zope module, qui est utilisé par des projets en dehors de zope, comme tordu. Je ne le connais pas vraiment, mais il y a une page wiki ici cela pourrait aider.

En général, vous n'avez pas besoin du concept de classes abstraites ou d'interfaces en python (édité - voir la réponse de S.Lott pour plus de détails).


98
2017-12-16 17:51



Python n'a pas vraiment de concept.

Il utilise le typage de canard, ce qui supprime le besoin d'interfaces (du moins pour l'ordinateur :-))

Python <= 2.5: Les classes de base existent évidemment, mais il n'y a pas de moyen explicite de marquer une méthode comme étant «virtuelle pure», la classe n'est donc pas vraiment abstraite.

Python> = 2.6: Classes de base abstraites exister (http://docs.python.org/library/abc.html). Et vous permettent de spécifier les méthodes qui doivent être implémentées dans les sous-classes. Je n'aime pas beaucoup la syntaxe, mais la fonctionnalité est là. La plupart du temps, il est probablement préférable d'utiliser le typage de canard du côté client.


35
2017-12-16 17:38



D'une manière plus basique d'expliquer: Une interface est un peu comme un moule à muffins vide. C'est un fichier de classe avec un ensemble de définitions de méthodes qui n'ont pas de code.

Une classe abstraite est la même chose, mais toutes les fonctions ne doivent pas être vides. Certains peuvent avoir du code. Ce n'est pas strictement vide.

Pourquoi différencier: Il n'y a pas beaucoup de différence pratique en Python, mais au niveau de la planification pour un grand projet, il peut être plus courant de parler d'interfaces, puisqu'il n'y a pas de code. Surtout si vous travaillez avec des programmeurs Java habitués à ce terme.


27
2018-05-08 17:51



En général, les interfaces ne sont utilisées que dans les langages utilisant le modèle de classe à héritage unique. Dans ces langages à héritage unique, les interfaces sont généralement utilisées si n'importe quelle classe peut utiliser une méthode ou un ensemble de méthodes particulier. Toujours dans ces langages à héritage unique, les classes abstraites sont utilisées pour avoir des variables de classe définies en plus d'aucune ou plusieurs méthodes, ou pour exploiter le modèle à héritage unique pour limiter la plage de classes pouvant utiliser un ensemble de méthodes.

Les langages qui prennent en charge le modèle à héritage multiple ont tendance à utiliser uniquement des classes ou des classes de base abstraites et non des interfaces. Étant donné que Python prend en charge l'héritage multiple, il n'utilise pas d'interfaces et vous souhaitez utiliser des classes de base ou des classes de base abstraites.

http://docs.python.org/library/abc.html


16
2017-12-16 18:19