Différence entre la classe abstraite et l'interface en Python

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

452
demandé sur Casebash 2008-12-16 20:32:27

6 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) de contrat D'Interface formel, la distinction de style Java entre abstraction et interface n'existe pas. Si quelqu'un passe par la définition d'une interface formelle, il sera aussi une classe abstraite. Les seules différences résideraient dans l'intention énoncée dans la fiche descriptive.

et la différence entre abstrait et l'interface est une chose capillaire quand vous avez la dactylographie de canard.

Java utilise des interfaces parce qu'il n'a pas d'héritage multiple.

parce que Python a un héritage multiple, vous pouvez aussi voir quelque chose comme ça""

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 superclasse abstraite avec des mixines pour créer des sous-classes de béton qui sont disjointes.

522
répondu S.Lott 2008-12-16 18:58:26

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

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

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

utilisant une classe de base abstraite

par exemple, disons que nous voulons utiliser une des classes de base abstraites de la collections module:

import collections
class MySet(collections.Set):
    pass

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

>>> 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__

donc nous sommes tenus de mettre en œuvre au moins __contains__ , __iter__ , et __len__ . Utilisons cet exemple d'implémentation 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

Mise en œuvre: Création D'une classe de base abstraite

nous pouvons créer notre propre classe de Base abstraite en mettant le metaclass à abc.ABCMeta et en utilisant le décorateur abc.abstractmethod sur les méthodes pertinentes. Le metaclass sera ajouter les fonctions décorées à l'attribut __abstractmethods__ , empêchant l'instanciation jusqu'à ce que ceux-ci sont définis.

import abc

Par exemple, "effable" est défini comme quelque chose qui peut être exprimée en mots. Disons que nous voulions définissez une classe de base abstraite qui est effable, 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 en Python 3, avec la légère modification de la déclaration metaclass:

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 effaçable sans implémenter l'interface:

class MyEffable(Effable): 
    pass

et tenter 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 se conformer en fournissant l'interface attendue:

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

nous sommes alors en mesure d'utiliser la version concrète de la classe dérivée à partir de l'abstrait:

>>> 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 c'est au-delà de la portée de cette question. Les autres méthodes démontrées ici devraient adapter cette méthode en utilisant le module abc pour le faire, cependant.

Conclusion

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

141
répondu Aaron Hall 2017-11-21 21:28:14

Python > = 2.6 A classes de base abstraites .

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

il y a aussi le Zope Interface module, qui est utilisé par les projets en dehors de zope, comme twisted. Je ne le connais pas vraiment, mais il y a une page wiki ici qui 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
répondu JimB 2013-03-05 20:28:40

Python n'a pas vraiment l'un ou l'autre concept.

il utilise du duck typing, qui a supprimé le besoin d'interfaces (au moins pour l'ordinateur: -))

Python < = 2,5: Les classes de Base existent évidemment, mais il n'y a pas de façon explicite de marquer une méthode comme 'pure virtuelle', donc la classe n'est pas vraiment abstraite.

Python > = 2,6: Les classes de base abstraites ne exister ( http://docs.python.org/library/abc.html ). Et vous permet 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 duck typing du côté du client "using".

35
répondu Douglas Leeder 2008-12-16 22:49:04

d'une manière plus basique pour expliquer: Une interface, c'est comme un muffin 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 pas toutes les fonctions doivent être vides. Certains peuvent avoir un code. Il 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 pourrait être plus fréquent de parler interfaces, puisqu'il n'y a pas de code. Surtout si vous travaillez avec des programmeurs Java habitués à ce terme.

27
répondu SilentSteel 2013-05-08 17:51:11

en général, les interfaces ne sont utilisées que dans les langues qui utilisent le modèle de classe de transmission unique. Dans ces langages à héritage unique, les interfaces sont généralement utilisées si une classe quelconque peut utiliser une méthode ou un ensemble de méthodes particulier. En outre, dans ces langues à héritage unique, les classes abstraites sont utilisées soit pour avoir des variables de classe définies en plus de AUCUNE ou plusieurs méthodes, soit pour exploiter le modèle à héritage unique pour limiter la gamme de classes qui pourraient utiliser un ensemble de méthodes.

les langues qui prennent en charge le modèle d'héritage multiple ont tendance à n'utiliser que des classes ou des classes de base abstraites et non des interfaces. Puisque Python supporte l'héritage multiple, il n'utilise pas d'interfaces et vous voudriez utiliser des classes de base ou des classes de base abstraites.

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

15
répondu Lara Dougan 2008-12-16 18:19:55