When I define a class, I like to include type checking (using assert
) of the input variables. I am now defining a 'specialized' class Rule
which inherits from an abstract base class (ABC) BaseRule
, similar to the following:
import abc
class BaseRule(object):
__metaclass__ = abc.ABCMeta
@abc.abstractproperty
def resources(self):
pass
class Rule(BaseRule):
def __init__(self, resources):
assert all(isinstance(resource, Resource) for resource in resources) # type checking
self._resources = resources
@property
def resources(self):
return self._resources
class Resource(object):
def __init__(self, domain):
self.domain = domain
if __name__ == "__main__":
resources = [Resource("facebook.com")]
rule = Rule(resources)
The assert
statement in the __init__
function of the Rule
class ensures that the resources
input is a list (or other iterable) of Resource
objects. However, this would also be the case for other classes which inherit from BaseRule
, so I would like to incorporate this assertion in the abstractproperty
somehow. How might I go about this?
Make your base class have a non-abstract property that calls separate abstract getter and setter methods. The property can do the validation you want before calling the setter. Other code (such as the __init__
method of a derived class) that wants to trigger the validation can do so by doing its assignment via the property:
class BaseRule(object):
__metaclass__ = abc.ABCMeta
@property
def resources(self): # this property isn't abstract and shouldn't be overridden
return self._get_resources()
@resources.setter
def resources(self, value):
assert all(isinstance(resource, Resources) for resource in value)
self._set_resources(value)
@abstractmethod
def _get_resources(self): # these methods should be, instead
pass
@abstractmethod
def _set_resources(self, value):
pass
class Rule(BaseRule):
def __init__(self, resources):
self.resources = resources # assign via the property to get type-checking!
def _get_resources(self):
return self._resources
def _set_resources(self, value):
self._resources = value
You might even consider moving the __init__
method from Rule
into the BaseRule
class, since it doesn't need any knowledge about Rule
's concrete implementation.