Diferencia entre clase abstracta e interfaz en Python


¿Cuál es la diferencia entre la clase abstracta y la interfaz en Python?

Author: Casebash, 2008-12-16

6 answers

Lo que verás a veces es lo siguiente:

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" )

Debido a que Python no tiene (y no necesita) un contrato de interfaz formal, la distinción de estilo Java entre abstracción e interfaz no existe. Si alguien pasa por el esfuerzo de definir una interfaz formal, también será una clase abstracta. Las únicas diferencias estarían en la intent declarada en el docstring.

Y la diferencia entre lo abstracto y la interfaz es una cosa que divide el cabello cuando tienes pato teclear.

Java utiliza interfaces porque no tiene herencia múltiple.

Debido a que Python tiene herencia múltiple, también puede ver algo como esto

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

Esto utiliza una especie de superclase abstracta con mixins para crear subclases concretas que son disjuntos.

 522
Author: S.Lott,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2008-12-16 18:58:26

¿Cuál es la diferencia entre la clase abstracta y la interfaz en Python?

Una interfaz, para un objeto, es un conjunto de métodos y atributos en ese objeto.

En Python, podemos usar una clase base abstracta para definir y hacer cumplir una interfaz.

Usando una Clase Base Abstracta

Por ejemplo, digamos que queremos usar una de las clases base abstractas del módulo collections:

import collections
class MySet(collections.Set):
    pass

Si tratamos de usarlo, obtenemos un TypeError porque el la clase que creamos no soporta el comportamiento esperado de los conjuntos:

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

Así que estamos obligados a implementar al menos __contains__, __iter__, y __len__. Usemos este ejemplo de implementación de la documentación :

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

Implementación: Creación de una Clase Base Abstracta

Podemos crear nuestra propia Clase Base Abstracta estableciendo la metaclase en abc.ABCMeta y usando el decorador abc.abstractmethod en los métodos relevantes. La metaclase se añadirá el decorado funciones al atributo __abstractmethods__, evitando la instanciación hasta que se definan.

import abc

Por ejemplo, "effable" se define como algo que se puede expresar en palabras. Digamos que queremos definir una clase base abstracta que sea 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')

O en Python 3, con el ligero cambio en la declaración de metaclase:

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

Ahora si intentamos crear un objeto effable sin implementar la interfaz:

class MyEffable(Effable): 
    pass

E intentar instanciar it:

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

Se nos dice que no hemos terminado el trabajo.

Ahora si cumplimos proporcionando la interfaz esperada:

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

Entonces podemos usar la versión concreta de la clase derivada de la abstracta: {[24]]}

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

Hay otras cosas que podríamos hacer con esto, como registrar subclases virtuales que ya implementan estas interfaces, pero creo que eso está más allá del alcance de esta pregunta. Los otros métodos aquí demostrados tendrían que adaptarse este método utiliza el módulo abc para hacerlo, sin embargo.

Conclusión

Hemos demostrado que la creación de una Clase Base Abstracta define interfaces para objetos personalizados en Python.

 141
Author: Aaron Hall,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-11-21 21:28:14

Python >= 2.6 tiene Clases Base Abstractas.

Clases Base Abstractas (abreviadas ABCs) complement duck-typing by proporcionar una forma de definir interfaces cuando otras técnicas como hasattr() sería torpe. Python viene con muchos ABCs incorporados para estructuras de datos (en el módulo colecciones), números (en el módulo numbers), y flujos (en el módulo io). Puede crear su propio ABC con el módulo abc.

También está el Zope Módulo Interfaz, que es utilizado por proyectos fuera de zope, como twisted. No estoy muy familiarizado con él, pero hay una página wiki aquí que podría ayudar.

En general, no necesita el concepto de clases abstractas, o interfaces en python (editado - vea la respuesta de S. Lott para más detalles).

 98
Author: JimB,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2013-03-05 20:28:40

Python realmente no tiene ninguno de los dos conceptos.

Utiliza duck typing, lo que elimina la necesidad de interfaces (al menos para el equipo :-))

Python

Python >= 2.6: Las clases base abstractas do existen (http://docs.python.org/library/abc.html ). Y le permiten especificar métodos que deben implementarse en subclases. No me gusta mucho la sintaxis, pero la característica está ahí. La mayoría de las veces es probablemente mejor usar duck typing desde el lado del cliente 'using'.

 35
Author: Douglas Leeder,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2008-12-16 22:49:04

De una manera más básica para explicar: Una interfaz es como una bandeja de magdalenas vacía. Es un archivo de clase con un conjunto de definiciones de métodos que no tienen código.

Una clase abstracta es lo mismo, pero no todas las funciones necesitan estar vacías. Algunos pueden tener código. No está estrictamente vacío.

Por qué diferenciar: No hay mucha diferencia práctica en Python, pero a nivel de planificación para un proyecto grande, podría ser más común hablar de interfaces, ya que no hay código. Especialmente si estás trabajando con programadores Java que están acostumbrados al término.

 27
Author: SilentSteel,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2013-05-08 17:51:11

En general, las interfaces se usan solo en lenguajes que usan el modelo de clase de herencia única. En estos lenguajes de herencia única, las interfaces se usan típicamente si cualquier clase puede usar un método o conjunto de métodos en particular. También en estos lenguajes de herencia única, las clases abstractas se utilizan para tener variables de clase definidas además de ninguno o más métodos, o para explotar el modelo de herencia única para limitar el rango de clases que podrían usar un conjunto de métodos.

Los lenguajes que soportan el modelo de herencia múltiple tienden a usar solo clases o clases base abstractas y no interfaces. Dado que Python admite herencia múltiple, no usa interfaces y usted querría usar clases base o clases base abstractas.

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

 15
Author: Lara Dougan,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2008-12-16 18:19:55