Hoe implementeer ik interfaces in Python?

Hoe implementeer ik Python-equivalent van deze C # -code?

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!'

Is dit een goed idee ?? Geef voorbeelden in uw antwoorden.


1, Autoriteit 100%

Zoals vermeld door andere hier:

Interfaces zijn niet nodig in Python. Dit komt omdat Python een goede overerving heeft, en ook duckyping, wat betekent dat de plaatsen waar u Moet een interfaces in Java moeten hebben, u ze niet in Python hoeft te hebben.

Dat gezegd hebbende, er zijn nog steeds verschillende toepassingen voor interfaces. Sommigen van hen zijn bedekt met pythons abstracte base-klassen, geïntroduceerd in Python 2.6. Ze zijn nuttig, als u basklases wilt maken die niet kunnen worden geïnstantieerd, maar een specifieke interface of een deel van een implementatie bieden.

Een ander gebruik is als u op de een of andere manier wilt specificeren dat een object een specifieke interface implementeert, en u kunt ABC’s daarvoor ook gebruiken door ze van hen te onderschakelen. Een andere manier is zope.interface, een module die deel uitmaakt van de zope-componentarchitectuur, een echt eenzaam cool component framework. Hier sluit je niet uit de interfaces, maar markeer in plaats daarvan klassen (of zelfs gevallen) als implementatie van een interface. Dit kan ook worden gebruikt om componenten van een componentregister op te zoeken. Supercool!


2, Autoriteit 52%

Gebruik van de ABC-module voor abstracte basisklassen lijkt de truc te doen.

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

3, Autoriteit 40%

implementeren interfaces met abstracte basisklassen is veel eenvoudiger in moderne Python 3 en ze dienen een doel als interface contract voor plug-in extensions.

Maak de interface / abstracte basisklasse:

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)

Een normale subklasse en overschrijven alle abstracte methoden:

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)

U kunt optioneel een gemeenschappelijke implementatie hebben in de abstracte methoden zoals in create_sale_invoice(), door het expliciet aan te roepen met super()in de subklasse zoals hierboven.

Instantiatie van een subklasse die niet alle abstracte methoden implementeert mislukt:

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

Je kunt ook abstracte eigenschappen, statische en klassenmethoden gebruiken door de bijbehorende annotaties te combineren met @abstractmethod.

Abstracte basisklassen zijn geweldig voor het implementeren van op plug-ins gebaseerde systemen. Alle geïmporteerde subklassen van een klasse zijn toegankelijk via __subclasses__(), dus als je alle klassen laadt uit een plugin-directory met importlib.import_module()en als ze de basisklasse subklassen , u hebt er rechtstreeks toegang toe via __subclasses__()en u kunt er zeker van zijn dat het interfacecontract voor hen allemaal wordt afgedwongen tijdens de instantiatie.

Hier is de implementatie voor het laden van plug-ins voor het bovenstaande voorbeeld AccountingSystem:

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

Vervolgens hebt u toegang tot het plug-inobject voor het boekhoudsysteem via de klasse AccountingSystem:

>>> accountingsystem = AccountingSystem.instance()

(Geïnspireerd door dit PyMOTW-3 bericht.)


Antwoord 4, autoriteit 28%

interfaceondersteunt Python 2.7 en Python 3.4+.

Om de installeerinterface moet je

pip install python-interface

Voorbeeldcode:

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

Antwoord 5, autoriteit 21%

Er zijn implementaties van interfaces van derden voor Python (de meest populaire zijn Zope’s, ook gebruikt in Twisted), maar meestal gebruiken Python-codeerders de rijkere concept dat bekend staat als een “Abstract Base Class” (ABC), dat een interface combineert met de mogelijkheid om daar ook enkele implementatieaspecten te hebben. ABC’s worden bijzonder goed ondersteund in Python 2.6 en later, zie de PEP, maar zelfs in eerdere versies van Python worden ze normaal gezien als “de weg te gaan” – definieer gewoon een klasse waarvan sommige methoden NotImplementedErrorverhogen, zodat subklassen opmerken dat ze beter kunnen overschrijven die methoden!-)


Antwoord 6, autoriteit 12%

Zoiets (werkt misschien niet omdat ik geen Python in de buurt heb):

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

7, Autoriteit 5%

Mijn begrip is dat interfaces niet zo nodig zijn in dynamische talen zoals Python. In Java (of C++ met zijn abstracte basisklasse) zijn interfaces middelen om ervoor te zorgen dat b.v. Je passeert de juiste parameter, in staat om set taken uit te voeren.

b.g. Als u waarnemer en waarneembaar heeft, is waarneembaar geïnteresseerd in het inschrijven van objecten die IOBSERVER-interface ondersteunt, die op zijn beurt notify. Dit wordt gecontroleerd op compileertijd.

In Python is er niet zoiets als compile timeen Method-lookups worden uitgevoerd bij runtime. Bovendien kan men opzoeken met __getattr __ () of __getattribute __ () magische methoden. Met andere woorden, u kunt als waarnemer enig object passeren dat u wilt retourneren op het gebied van toegang tot notifykenmerk.

Dit leidt mij tot de conclusie, dat interfaces in Python bestaan – het is gewoon hun handhaving wordt uitgesteld tot het moment waarop ze daadwerkelijk worden gebruikt

Other episodes