Wie in den anderen Antworten erläutert, können Sie mit dem abc
Modul abstrakte Klassen in Python verwenden . Im Folgenden gebe ich ein tatsächliches Beispiel mit abstraktem @classmethod
, @property
und @abstractmethod
(mit Python 3.6 oder höher). Für mich ist es normalerweise einfacher, mit Beispielen zu beginnen, die ich einfach kopieren und einfügen kann. Ich hoffe, diese Antwort ist auch für andere nützlich.
Erstellen wir zunächst eine Basisklasse mit dem Namen Base
:
from abc import ABC, abstractmethod
class Base(ABC):
@classmethod
@abstractmethod
def from_dict(cls, d):
pass
@property
@abstractmethod
def prop1(self):
pass
@property
@abstractmethod
def prop2(self):
pass
@prop2.setter
@abstractmethod
def prop2(self, val):
pass
@abstractmethod
def do_stuff(self):
pass
Unsere Base
Klasse wird immer ein from_dict
classmethod
, ein property
prop1
(schreibgeschützt) und ein property
prop2
(das auch gesetzt werden kann) sowie eine aufgerufene Funktion haben do_stuff
. Unabhängig davon, auf welcher Klasse jetzt basiert Base
, muss all dies für Methoden / Eigenschaften implementiert werden. Bitte beachten Sie, dass für eine abstrakte Methode zwei Dekorateure erforderlich sind - classmethod
und eine abstrakte property
.
Jetzt könnten wir eine Klasse A
wie diese erstellen :
class A(Base):
def __init__(self, name, val1, val2):
self.name = name
self.__val1 = val1
self._val2 = val2
@classmethod
def from_dict(cls, d):
name = d['name']
val1 = d['val1']
val2 = d['val2']
return cls(name, val1, val2)
@property
def prop1(self):
return self.__val1
@property
def prop2(self):
return self._val2
@prop2.setter
def prop2(self, value):
self._val2 = value
def do_stuff(self):
print('juhu!')
def i_am_not_abstract(self):
print('I can be customized')
Alle erforderlichen Methoden / Eigenschaften sind implementiert und wir können natürlich auch zusätzliche Funktionen hinzufügen, die nicht Teil von Base
(hier :) sind i_am_not_abstract
.
Jetzt können wir tun:
a1 = A('dummy', 10, 'stuff')
a2 = A.from_dict({'name': 'from_d', 'val1': 20, 'val2': 'stuff'})
a1.prop1
# prints 10
a1.prop2
# prints 'stuff'
Wie gewünscht können wir nicht einstellen prop1
:
a.prop1 = 100
wird zurückkehren
AttributeError: Attribut kann nicht festgelegt werden
Auch unsere from_dict
Methode funktioniert gut:
a2.prop1
# prints 20
Wenn wir jetzt eine zweite Klasse B
wie diese definieren:
class B(Base):
def __init__(self, name):
self.name = name
@property
def prop1(self):
return self.name
und versuchte, ein Objekt wie folgt zu instanziieren:
b = B('iwillfail')
Wir werden einen Fehler bekommen
TypeError: Abstrakte Klasse B kann nicht mit abstrakten Methoden do_stuff, from_dict, prop2 instanziiert werden
Auflisten aller definierten Dinge, in Base
denen wir nicht implementiert haben B
.