Como posso implementar interfaces em python?

public interface IInterface
{
    void show();
}

 public class MyClass : IInterface
{

    #region IInterface Members

    public void show()
    {
        Console.WriteLine("Hello World!");
    }

    #endregion
}

Como posso implementar o equivalente Python deste 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!'
Isto é uma boa ideia?? Por favor, dê exemplos nas suas respostas.

 78
Author: Byte Commander, 2010-01-23

6 answers

Como mencionado por outro aqui:

As Interfaces

Não são necessárias em Python. Isto é porque Python tem herança múltipla adequada, e também ducktyping, o que significa que os lugares onde você deve ter interfaces em Java, você não precisa tê-las em Python.

Dito isto, ainda existem vários usos para interfaces. Alguns deles são cobertos por Classes Base abstratas Pythons, introduzidas em python 2.6. Eles são úteis, se você quiser fazer classes de base que não pode seja instanciado, mas forneça uma interface específica ou parte de uma implementação.

Outra utilização é se você de alguma forma quiser especificar que um objeto implementa uma interface específica, e você pode usar o ABC para isso também subclassificando a partir deles. Outra maneira é zope.interface, um módulo que faz parte da arquitetura de componentes Zope, um framework de componentes muito legal. Aqui você não subclasse das interfaces, mas em vez disso marque classes (ou mesmo instâncias) como a implementação de um interface. Isto também pode ser usado para procurar componentes de um registro de componentes. Super fixe!

 78
Author: Lennart Regebro, 2017-11-17 13:49:41

Usar o módulo abc para classes de base abstractas parece fazer o truque.

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()
 30
Author: Peter Torpman, 2014-04-17 13:11:36

Há de terceiros implementações de interfaces para Python (o mais popular é Zope do, usado também em Torcida), mas, mais comumente, Python programadores preferem usar o mais rico do conceito conhecido como uma "Classe Base Abstrata" (ABC), que combina uma interface com a possibilidade de ter alguns aspectos de implementação lá também. Os ABCs são particularmente bem suportados no Python 2.6 e mais tarde, veja o PEP , mas mesmo em versões anteriores do Python eles são normalmente vistos como "the way to go" -- basta definir uma classe cujos métodos aumentam {[[0]} para que as subclasses estejam cientes de que é melhor eles ultrapassarem esses métodos!-)

 21
Author: Alex Martelli, 2010-01-23 18:33:56

Algo assim (pode não funcionar porque eu não tenho Python por perto):

class IInterface:
    def show(self): raise NotImplementedError

class MyClass(IInterface):
    def show(self): print "Hello World!"
 13
Author: Bandi-T, 2010-01-23 18:36:23

O meu entendimento é que as interfaces não são necessárias em linguagens dinâmicas como o Python. Em Java (ou C++ com sua classe base abstrata) interfaces são meios para garantir que, por exemplo, você está passando o parâmetro certo, capaz de executar um conjunto de Tarefas.

Por exemplo, se tiver observador e observável, o observável está interessado em subscrever objectos que suportam a interface do Ioblerver, que por sua vez tem notify acção. Esta opção está assinalada na hora de compilação.

Em Python, não há coisas como compile time e pesquisas de métodos são realizadas em tempo de execução. Além disso, pode-se sobrepor a pesquisa com __getattr__() ou _getattribute ___ () métodos mágicos. Em outras palavras, você pode passar, como observador, qualquer objeto que possa retornar ligável ao acessar o atributo notify.

Isto leva - me à conclusão de que as interfaces em Python existem [[11]} - é que a sua aplicação é adiada para o momento em que são realmente usadas
 6
Author: Tomasz Zielinski, 2010-01-23 19:19:41

A implementação de interfaces com classes de base abstractas é muito mais simples no Python 3 moderno e servem como um contrato de interface para extensões plug-in.

Crie a classe de base interface / abstract:

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)

Criar uma subclasse normal e sobrepor todos os 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)

Você pode opcionalmente ter implementação comum nos métodos abstratos como em create_sale_invoice(), chamando-o com super() explicitamente na subclasse como acima.

Instanciação de uma subclasse que não implementa todos os métodos abstratos falha:

class IncompleteAccountingSystem(AccountingSystem):
    pass

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

Também pode ter propriedades abstractas, métodos estáticos e de classe combinando anotações correspondentes com @abstractmethod.

As classes de base Abstractas são óptimas para implementar sistemas baseados em Plugins. Todas as subclasses importadas de uma classe estão acessíveis através de __subclasses__(), por isso, se carregar todas as classes de uma pasta de 'plugins' com importlib.import_module() e se subclassificarem a classe base, terá acesso directo a elas através de __subclasses__() e você pode ter certeza de que o contrato de interface é executado para todos eles durante a instanciação.

Aqui está a implementação de carregamento do plugin para o exemplo acima:

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

Depois poderá aceder ao objecto do plugin do sistema de Contabilidade através da classe AccountingSystem:

>>> accountingsystem = AccountingSystem.instance()

(inspirado por Este PyMOTW - 3 post .)

 1
Author: mrts, 2018-07-14 12:23:42