Assume you're writing an abstract class and one or more of its non-abstract class methods require the concrete class to have a specific class attribute; e.g., if instances of each concrete class can be constructed by matching against a different regular expression, you might want to give your ABC the following:
@classmethod
def parse(cls, s):
m = re.fullmatch(cls.PATTERN, s)
if not m:
raise ValueError(s)
return cls(**m.groupdict())
(Maybe this could be better implemented with a custom metaclass, but try to ignore that for the sake of the example.)
Now, because overriding of abstract methods & properties is checked at instance creation time, not subclass creation time, trying to use abc.abstractmethod
to ensure concrete classes have PATTERN
attributes won't work — but surely there should be something there to tell anyone looking at your code "I didn't forget to define PATTERN
on the ABC; the concrete classes are supposed to define their own." The question is: Which something is the most Pythonic?
Pile of decorators
@property @abc.abstractmethod def PATTERN(self): pass
(Assume Python 3.4 or higher, by the way.) This can be very misleading to readers, as it implies that
PATTERN
should be an instance property instead of a class attribute.Tower of decorators
@property @classmethod @abc.abstractmethod def PATTERN(cls): pass
This can be very confusing to readers, as
@property
and@classmethod
normally can't be combined; they only work together here (for a given value of "work") because the method is ignored once it's overridden.Dummy value
PATTERN = ''
If a concrete class fails to define its own
PATTERN
,parse
will only accept empty input. This option isn't widely applicable, as not all use cases will have an appropriate dummy value.Error-inducing dummy value
PATTERN = None
If a concrete class fails to define its own
PATTERN
,parse
will raise an error, and the programmer gets what they deserve.Do nothing. Basically a more hardcore variant of #4. There can be a note in the ABC's docstring somewhere, but the ABC itself shouldn't have anything in the way of a
PATTERN
attribute.Other???