Wie in den anderen Antworten erläutert, können Sie abstrakte Klassen in Python mit der Option abc
Modul . Im Folgenden gebe ich ein konkretes Beispiel mit abstrakten @classmethod
, @property
y @abstractmethod
(mit Python 3.6+). Für mich ist es in der Regel 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 namens 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
Unser Base
Klasse hat immer eine from_dict
classmethod
, a property
prop1
(die schreibgeschützt ist) und eine property
prop2
(die auch gesetzt werden kann) sowie eine Funktion namens do_stuff
. Welche Klasse auch immer nun auf der Grundlage von Base
müssen alle diese vier Methoden/Eigenschaften implementieren. Bitte beachten Sie, dass für eine abstrakte Methode zwei Dekoratoren erforderlich sind - classmethod
und abstrakt property
.
Jetzt könnten wir eine Klasse erstellen A
wie diese:
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: i_am_not_abstract
).
Jetzt können wir es 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 die prop1
:
a.prop1 = 100
wird zurückgegeben
AttributeError: Attribut kann nicht gesetzt werden
Auch unser from_dict
Methode funktioniert gut:
a2.prop1
# prints 20
Wenn wir nun eine zweite Klasse definieren B
wie diese:
class B(Base):
def __init__(self, name):
self.name = name
@property
def prop1(self):
return self.name
und versucht, ein Objekt wie dieses zu instanziieren:
b = B('iwillfail')
erhalten wir eine Fehlermeldung
TypFehler: Kann die abstrakte Klasse B mit abstrakten Methoden nicht instanziieren do_stuff, from_dict, prop2
Auflistung aller Dinge, die in Base
die wir in den folgenden Bereichen nicht umgesetzt haben B
.