Come spiegato nelle altre risposte, sì, puoi usare le classi astratte in Python usando il abc
modulo . Qui di seguito un esempio reale utilizzando astratta @classmethod
, @property
e @abstractmethod
(utilizzando Python 3.6+). Per me è di solito più facile iniziare con esempi che posso facilmente copiare e incollare; Spero che questa risposta sia utile anche per gli altri.
Per prima cosa creiamo una classe base chiamata 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
La nostra Base
classe avrà sempre a from_dict
classmethod
, a property
prop1
(che è di sola lettura) e a property
prop2
(che può anche essere impostata) oltre a una funzione chiamata do_stuff
. Qualunque sia la classe ora costruita sulla base Base
dovrà implementare tutte queste per metodi / proprietà. Si noti che affinché un metodo sia astratto, sono necessari due decoratori - classmethod
e astratto property
.
Ora potremmo creare una classe A
come questa:
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')
Tutti i metodi / proprietà richiesti sono implementati e possiamo - ovviamente - anche aggiungere funzioni aggiuntive che non fanno parte Base
(qui:) i_am_not_abstract
.
Ora possiamo fare:
a1 = A('dummy', 10, 'stuff')
a2 = A.from_dict({'name': 'from_d', 'val1': 20, 'val2': 'stuff'})
a1.prop1
# prints 10
a1.prop2
# prints 'stuff'
Se lo si desidera, non è possibile impostare prop1
:
a.prop1 = 100
sarà di ritorno
AttributeError: impossibile impostare l'attributo
Anche il nostro from_dict
metodo funziona bene:
a2.prop1
# prints 20
Se ora abbiamo definito una seconda classe B
come questa:
class B(Base):
def __init__(self, name):
self.name = name
@property
def prop1(self):
return self.name
e ho provato a creare un'istanza di un oggetto come questo:
b = B('iwillfail')
avremo un errore
TypeError: impossibile creare un'istanza di classe B astratta con metodi astratti do_stuff, from_dict, prop2
elencando tutte le cose definite in Base
cui non abbiamo implementato B
.