As explained in the other answers, yes you can use abstract classes in Python using the abc
module. Below I give an actual example using abstract @classmethod
, @property
and @abstractmethod
(using Python 3.6+). For me it is usually easier to start off with examples I can easily copy&paste; I hope this answer is also useful for others.
Let's first create a base class called 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
Our Base
class will always have a from_dict
classmethod
, a property
prop1
(which is read-only) and a property
prop2
(which can also be set) as well as a function called do_stuff
. Whatever class is now built based on Base
will have to implement all of these four methods/properties. Please note that for a method to be abstract, two decorators are required - classmethod
and abstract property
.
Now we could create a class A
like this:
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')
All required methods/properties are implemented and we can - of course - also add additional functions that are not part of Base
(here: i_am_not_abstract
).
Now we can do:
a1 = A('dummy', 10, 'stuff')
a2 = A.from_dict({'name': 'from_d', 'val1': 20, 'val2': 'stuff'})
a1.prop1
# prints 10
a1.prop2
# prints 'stuff'
As desired, we cannot set prop1
:
a.prop1 = 100
will return
AttributeError: can't set attribute
Also our from_dict
method works fine:
a2.prop1
# prints 20
If we now defined a second class B
like this:
class B(Base):
def __init__(self, name):
self.name = name
@property
def prop1(self):
return self.name
and tried to instantiate an object like this:
b = B('iwillfail')
we will get an error
TypeError: Can't instantiate abstract class B with abstract methods
do_stuff, from_dict, prop2
listing all the things defined in Base
which we did not implement in B
.