Diferencia entre clase abstracta e interfaz en Python
¿Cuál es la diferencia entre la clase abstracta y la interfaz en Python?
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.
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.
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).
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'.
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.
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.
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