public interface IInterface
{
void show();
}
public class MyClass : IInterface
{
#region IInterface Members
public void show()
{
Console.WriteLine("Hello World!");
}
#endregion
}
Wie implementiere ich ein Python-Äquivalent zu diesem 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!'
Ist das eine gute Idee? Bitte geben Sie Beispiele in Ihren Antworten.
raise NotImplementedError
ist, wasshow
der Körper sein sollte - macht keinen Sinn, ein vollständig generisches zu erheben,Exception
wenn Python ein perfekt spezifisches eingebautes definiert! -)Antworten:
Wie von anderen hier erwähnt:
Schnittstellen sind in Python nicht erforderlich. Dies liegt daran , Python richtige Mehrfachvererbung hat, und auch Duck-Typing, was bedeutet , dass die Orte , wo Sie müssen Schnittstellen in Java haben, können Sie sich nicht in Python haben müssen.
Es gibt jedoch immer noch mehrere Verwendungsmöglichkeiten für Schnittstellen. Einige von ihnen werden von Pythons Abstract Base Classes abgedeckt, die in Python 2.6 eingeführt wurden. Sie sind nützlich, wenn Sie Basisklassen erstellen möchten, die nicht instanziiert werden können, aber eine bestimmte Schnittstelle oder einen Teil einer Implementierung bereitstellen.
Eine andere Verwendung ist, wenn Sie irgendwie angeben möchten, dass ein Objekt eine bestimmte Schnittstelle implementiert, und Sie können ABCs auch dafür verwenden, indem Sie eine Unterklasse von ihnen erstellen. Eine andere Möglichkeit ist zope.interface, ein Modul, das Teil der Zope Component Architecture ist, einem wirklich unglaublich coolen Komponentenframework. Hier werden keine Unterklassen von den Schnittstellen erstellt, sondern Klassen (oder sogar Instanzen) als Implementierung einer Schnittstelle markiert. Dies kann auch verwendet werden, um Komponenten aus einer Komponentenregistrierung nachzuschlagen. Super cool!
quelle
Die Verwendung des abc-Moduls für abstrakte Basisklassen scheint den Trick zu tun.
quelle
if not server.version() == '1.0': raise ...
? Ich verstehe diese Zeile nicht wirklich. Eine Erklärung wäre willkommen.Die Schnittstelle unterstützt Python 2.7 und Python 3.4+.
Um die Schnittstelle zu installieren , müssen Sie
Beispielcode:
quelle
Das Implementieren von Schnittstellen mit abstrakten Basisklassen ist in modernem Python 3 viel einfacher und dient als Schnittstellenvertrag für Plug-In-Erweiterungen.
Erstellen Sie die Schnittstelle / abstrakte Basisklasse:
Erstellen Sie eine normale Unterklasse und überschreiben Sie alle abstrakten Methoden:
Sie können optional eine gemeinsame Implementierung in den abstrakten Methoden wie in
create_sale_invoice()
haben und diesesuper()
wie oben explizit in der Unterklasse aufrufen .Die Instanziierung einer Unterklasse, die nicht alle abstrakten Methoden implementiert, schlägt fehl:
Sie können auch abstrakte Eigenschaften, statische und Klassenmethoden verwenden, indem Sie entsprechende Anmerkungen mit kombinieren
@abstractmethod
.Abstrakte Basisklassen eignen sich hervorragend für die Implementierung von Plugin-basierten Systemen. Auf alle importierten Unterklassen einer Klasse kann über
__subclasses__()
zugegriffen werden. Wenn Sie also alle Klassen aus einem Plugin-Verzeichnis mit ladenimportlib.import_module()
und wenn sie die Basisklasse unterklassifizieren, haben Sie direkten Zugriff auf sie über__subclasses__()
und Sie können sicher sein, dass der Schnittstellenvertrag für alle erzwungen wird sie während der Instanziierung.Hier ist die Implementierung zum Laden des Plugins für das
AccountingSystem
obige Beispiel:Anschließend können Sie über die
AccountingSystem
Klasse auf das Plugin-Objekt des Buchhaltungssystems zugreifen :(Inspiriert von diesem PyMOTW-3-Beitrag .)
quelle
Es gibt Implementierungen von Schnittstellen für Python von Drittanbietern (am beliebtesten sind Zopes , die auch in Twisted verwendet werden ), aber Python-Codierer bevorzugen häufiger das umfangreichere Konzept, das als "Abstract Base Class" (ABC) bekannt ist und eine Schnittstelle mit kombiniert die Möglichkeit, auch dort einige Implementierungsaspekte zu haben. ABCs werden in Python 2.6 und höher besonders gut unterstützt, siehe PEP , aber selbst in früheren Versionen von Python werden sie normalerweise als "der richtige Weg" angesehen. Definieren Sie einfach eine Klasse, deren Methoden teilweise ausgelöst werden,
NotImplementedError
sodass Unterklassen vorhanden sind auf Hinweis, dass sie diese Methoden besser überschreiben sollten! -)quelle
So etwas (funktioniert möglicherweise nicht, da ich kein Python in der Nähe habe):
quelle
__init__(self)
dem Konstruktor tun ?abc.ABC
ist es viel besser als das Erhöhen. DieNotImplementedError
Instanziierung einerabc.ABC
Unterklasse, die nicht alle abstrakten Methoden implementiert, schlägt früh fehl, sodass Sie vor Fehlern geschützt sind. In meiner Antwort unten sehen Sie, wie der Fehler aussieht.Mein Verständnis ist, dass Schnittstellen in dynamischen Sprachen wie Python nicht so notwendig sind. In Java (oder C ++ mit seiner abstrakten Basisklasse) sind Schnittstellen Mittel, um sicherzustellen, dass Sie beispielsweise den richtigen Parameter übergeben und eine Reihe von Aufgaben ausführen können.
Wenn Sie beispielsweise Observer und Observable haben, ist Observable daran interessiert, Objekte zu abonnieren, die die IObserver-Schnittstelle unterstützen, die wiederum
notify
Aktionen ausführt . Dies wird beim Kompilieren überprüft.In Python gibt es keine
compile time
und Methodensuchen werden zur Laufzeit durchgeführt. Darüber hinaus kann die Suche mit den magischen Methoden __getattr __ () oder __getattribute __ () überschrieben werden. Mit anderen Worten, Sie können als Beobachter jedes Objekt übergeben, das beim Zugriff auf dasnotify
Attribut als aufrufbar zurückgegeben werden kann.Dies führt mich zu dem Schluss, dass Schnittstellen in Python existieren - es ist nur, dass ihre Durchsetzung auf den Moment verschoben wird, in dem sie tatsächlich verwendet werden
quelle