¿Cómo implemento interfaces en python?

public interface IInterface { void show(); } public class MyClass : IInterface { #region IInterface Members public void show() { Console.WriteLine("Hello World!"); } #endregion } 

¿Cómo implemento Python equivalente de este código C #?

 class IInterface(object): def __init__(self): pass def show(self): raise Exception("NotImplementedException") class MyClass(IInterface): def __init__(self): IInterface.__init__(self) def show(self): print 'Hello World!' 

¿¿Es esta una buena idea?? Por favor, da ejemplos en tus respuestas.

Como lo mencionó otro aquí:

Las interfaces no son necesarias en Python. Esto se debe a que Python tiene la herencia múltiple adecuada, y también el pataleo, lo que significa que los lugares donde debe tener interfaces en Java, no es necesario que estén en Python.

Dicho esto, todavía hay varios usos para las interfaces. Algunos de ellos están cubiertos por las clases básicas abstractas de Pythons, introducidas en Python 2.6. Son útiles, si desea crear clases base que no puedan ser instanciadas, pero que proporcionen una interfaz específica o parte de una implementación.

Otro uso es si de alguna manera desea especificar que un objeto implementa una interfaz específica, y puede usar ABC para eso también mediante la subclasificación de ellos. Otra forma es zope.interface, un módulo que forma parte de la Arquitectura de componentes de Zope, un marco de componentes realmente asombroso. Aquí no hace una subclase de las interfaces, sino que marca clases (o incluso instancias) como implementación de una interfaz. Esto también se puede utilizar para buscar componentes de un registro de componentes. ¡Super guay!

Usar el módulo abc para clases base abstractas parece hacer el truco.

 from abc import ABCMeta, abstractmethod class IInterface: __metaclass__ = ABCMeta @classmethod def version(self): return "1.0" @abstractmethod def show(self): raise NotImplementedError class MyServer(IInterface): def show(self): print 'Hello, World 2!' class MyBadServer(object): def show(self): print 'Damn you, world!' class MyClient(object): def __init__(self, server): if not isinstance(server, IInterface): raise Exception('Bad interface') if not IInterface.version() == '1.0': raise Exception('Bad revision') self._server = server def client_show(self): self._server.show() # This call will fail with an exception try: x = MyClient(MyBadServer) except Exception as exc: print 'Failed as it should!' # This will pass with glory MyClient(MyServer()).client_show() 

Existen implementaciones de interfaces de terceros para Python (la más popular es Zope , también usada en Twisted ), pero más comúnmente los codificadores de Python prefieren usar el concepto más rico conocido como “Clase Base Abstracta” (ABC), que combina una interfaz con La posibilidad de tener algunos aspectos de implementación allí también. Los ABC están particularmente bien soportados en Python 2.6 y más adelante, vea el PEP , pero incluso en versiones anteriores de Python normalmente se los ve como “el camino a seguir”, simplemente defina una clase cuyos métodos aumentan el NotImplementedError para que las subclases ¡Ten en cuenta que es mejor que anulen esos métodos!

Algo como esto (podría no funcionar porque no tengo Python):

 class IInterface: def show(self): raise NotImplementedError class MyClass(IInterface): def show(self): print "Hello World!" 

la interfaz es compatible con Python 2.7 y Python 3.4+.

Para instalar la interfaz tienes que

 pip install python-interface 

Código de ejemplo:

 from interface import implements, Interface class MyInterface(Interface): def method1(self, x): pass def method2(self, x, y): pass class MyClass(implements(MyInterface)): def method1(self, x): return x * 2 def method2(self, x, y): return x + y 

La implementación de interfaces con clases base abstractas es mucho más simple en Python 3 moderno y sirve como un contrato de interfaz para extensiones de plug-in.

Crear la interfaz / clase base abstracta:

 from abc import ABC, abstractmethod class AccountingSystem(ABC): @abstractmethod def create_purchase_invoice(self, purchase): pass @abstractmethod def create_sale_invoice(self, sale): log.debug('Creating sale invoice', sale) 

Cree una subclase normal y anule todos los métodos abstractos:

 class GizmoAccountingSystem(AccountingSystem): def create_purchase_invoice(self, purchase): submit_to_gizmo_purchase_service(purchase) def create_sale_invoice(self, sale): super().create_sale_invoice(sale) submit_to_gizmo_sale_service(sale) 

Opcionalmente, puede tener una implementación común en los métodos abstractos como en create_sale_invoice() , llamándola con super() explícitamente en la subclase como anteriormente.

La creación de una subclase que no implementa todos los métodos abstractos falla:

 class IncompleteAccountingSystem(AccountingSystem): pass >>> accounting = IncompleteAccountingSystem() Traceback (most recent call last): File "", line 1, in  TypeError: Can't instantiate abstract class IncompleteAccountingSystem with abstract methods create_purchase_invoice, create_sale_invoice 

También puede tener propiedades abstractas, métodos estáticos y de clase combinando las anotaciones correspondientes con @abstractmethod .

Las clases base abstractas son excelentes para implementar sistemas basados ​​en complementos. Se puede acceder a todas las subclases importadas de una clase a través de __subclasses__() , por lo tanto, si carga todas las clases desde un directorio de plugins con importlib.import_module() y si subclasifican la clase base, tiene acceso directo a ellas a través de __subclasses__() y puede asegúrese de que el contrato de interfaz se cumpla para todos ellos durante la instanciación.

Aquí está la implementación de carga de complementos para el ejemplo AccountingSystem anterior:

 ... from importlib import import_module class AccountingSystem(ABC): ... _instance = None @classmethod def instance(cls): if not cls._instance: module_name = settings.ACCOUNTING_SYSTEM_MODULE_NAME import_module(module_name) subclasses = cls.__subclasses__() if len(subclasses) > 1: raise InvalidAccountingSystemError('More than one ' f'accounting module: {subclasses}') if not subclasses or module_name not in str(subclasses[0]): raise InvalidAccountingSystemError('Accounting module ' f'{module_name} does not exist or does not ' 'subclass AccountingSystem') cls._instance = subclasses[0]() return cls._instance 

Luego, puede acceder al objeto de complemento del sistema de contabilidad a través de la clase AccountingSystem :

 >>> accountingsystem = AccountingSystem.instance() 

(Inspirado en esta publicación de PyMOTW-3 ).

Mi entendimiento es que las interfaces no son tan necesarias en lenguajes dynamics como Python. En Java (o C ++ con su clase base abstracta) las interfaces son medios para garantizar que, por ejemplo, está pasando el parámetro correcto, capaz de realizar un conjunto de tareas.

Por ejemplo, si tiene observador y observable, observable está interesado en suscribir objetos que sean compatibles con la interfaz IObserver, que a su vez tiene una acción de notify . Esto se comprueba en el momento de la comstackción.

En Python, no existe el compile time y las búsquedas de métodos se realizan en tiempo de ejecución. Además, se puede anular la búsqueda con los métodos mágicos __getattr __ () o __getattribute __ (). En otras palabras, puede pasar, como observador, cualquier objeto que pueda devolverse al acceder al atributo de notify .

Esto me lleva a la conclusión de que las interfaces en Python existen , es solo que su aplicación se pospone hasta el momento en que realmente se usan