public interface IInterface
{
void show();
}
public class MyClass : IInterface
{
#region IInterface Members
public void show()
{
Console.WriteLine("Hello World!");
}
#endregion
}
Jak zaimplementować w języku Python odpowiednik tego kodu 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!'
Czy to dobry pomysł? Podaj przykłady w swoich odpowiedziach.
raise NotImplementedError
jest tymshow
, czym powinno być ciało - nie ma sensu podnosić całkowicie ogólnego,Exception
gdy Python definiuje doskonale specyficzny wbudowany! -)Odpowiedzi:
Jak wspomniano tutaj:
Interfejsy nie są konieczne w Pythonie. Wynika to z faktu, że Python ma odpowiednie wielokrotne dziedziczenie, a także unikanie, co oznacza, że w miejscach, w których musisz mieć interfejsy w Javie, nie musisz ich mieć w Pythonie.
To powiedziawszy, wciąż istnieje kilka zastosowań interfejsów. Niektóre z nich są objęte Pythons Abstract Base Classes, wprowadzonymi w Pythonie 2.6. Są one przydatne, jeśli chcesz tworzyć klasy podstawowe, których nie można utworzyć instancji, ale zapewniają określony interfejs lub część implementacji.
Innym zastosowaniem jest, jeśli chcesz w jakiś sposób określić, że obiekt implementuje określony interfejs, i możesz również użyć do tego ABC, podklasując je. Innym sposobem jest zope.interface, moduł będący częścią Zope Component Architecture, naprawdę niesamowicie fajnego frameworka komponentów. W tym przypadku nie można podklasować interfejsów, ale zamiast tego oznaczać klasy (lub nawet instancje) jako implementujące interfejs. Można to również wykorzystać do wyszukiwania komponentów z rejestru komponentów. Super fajne!
źródło
Wydaje się, że użycie modułu abc do abstrakcyjnych klas bazowych jest wystarczające.
źródło
if not server.version() == '1.0': raise ...
:? Naprawdę nie rozumiem tej linii. Wyjaśnienie byłoby mile widziane.interfejs obsługuje Python 2.7 i Python 3.4+.
Aby zainstalować interfejs, musisz
Przykładowy kod:
źródło
Implementacja interfejsów z abstrakcyjnymi klasami podstawowymi jest znacznie prostsza we współczesnym Pythonie 3 i służą one jako umowa interfejsu dla rozszerzeń wtyczek.
Utwórz interfejs / abstrakcyjną klasę podstawową:
Utwórz normalną podklasę i zastąp wszystkie metody abstrakcyjne:
Opcjonalnie możesz mieć wspólną implementację metod abstrakcyjnych jak w
create_sale_invoice()
, wywołując jąsuper()
jawnie w podklasie, jak wyżej.Instancja podklasy, która nie implementuje wszystkich metod abstrakcyjnych, kończy się niepowodzeniem:
Możesz także mieć właściwości abstrakcyjne, metody statyczne i klasy, łącząc odpowiednie adnotacje z
@abstractmethod
.Abstrakcyjne klasy podstawowe świetnie nadają się do wdrażania systemów opartych na wtyczkach. Wszystkie zaimportowane podklasy klasy są dostępne przez
__subclasses__()
, więc jeśli załadujesz wszystkie klasy z katalogu wtyczekimportlib.import_module()
i jeśli podklasują one klasę podstawową, masz bezpośredni dostęp do nich przez__subclasses__()
i możesz być pewien, że umowa interfejsu jest egzekwowana dla wszystkich je podczas tworzenia.Oto implementacja ładowania wtyczki dla
AccountingSystem
powyższego przykładu:Następnie możesz uzyskać dostęp do obiektu wtyczki systemu księgowego poprzez
AccountingSystem
klasę:(Zainspirowany tym postem PyMOTW-3 .)
źródło
Istnieją implementacje interfejsów dla języka Python (najpopularniejsze to Zope , również używane w Twisted ), ale częściej kodery Python wolą używać bogatszej koncepcji znanej jako „Abstract Base Class” (ABC), która łączy interfejs z możliwość posiadania również niektórych aspektów wdrażania. ABC są szczególnie dobrze obsługiwane w Pythonie 2.6 i późniejszych, patrz PEP , ale nawet we wcześniejszych wersjach Pythona są zwykle postrzegane jako „droga do wyjścia” - wystarczy zdefiniować klasę, której niektóre metody wychowują
NotImplementedError
, aby podklasy były zauważając, że lepiej zastąpią te metody!)źródło
Coś takiego (może nie działać, ponieważ nie mam w pobliżu Pythona):
źródło
__init__(self)
z konstruktorem?abc.ABC
jest o wiele lepszy niż podnoszenieNotImplementedError
- tworzenie instancjiabc.ABC
podklasy, która nie implementuje wszystkich metod abstrakcyjnych, kończy się wcześnie, więc jesteś chroniony przed błędami. Zobacz moją odpowiedź poniżej, aby zobaczyć, jak wygląda błąd.Rozumiem, że interfejsy nie są tak potrzebne w dynamicznych językach, takich jak Python. W Javie (lub C ++ z abstrakcyjną klasą podstawową) interfejsy są sposobem na zapewnienie, że np. Przekazujesz odpowiedni parametr, zdolny do wykonania zestawu zadań.
Np. Jeśli masz obserwatora i jest obserwowalny, obserwowalny jest zainteresowany subskrybowaniem obiektów obsługujących interfejs IObserver, który z kolei ma
notify
akcję. Jest to sprawdzane podczas kompilacji.W Pythonie nie ma czegoś takiego,
compile time
a wyszukiwanie metod odbywa się w czasie wykonywania. Ponadto można zastąpić wyszukiwanie za pomocą magicznych metod __getattr __ () lub __getattribute __ (). Innymi słowy, możesz przekazać, jako obserwator, dowolny obiekt, który może zwrócić wywoływalne żądanie dostępunotify
.To prowadzi mnie do wniosku, że interfejsy w Pythonie istnieją - po prostu ich egzekwowanie jest odroczone do momentu, w którym są faktycznie używane
źródło