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
PATTERNshould be an instance property instead of a class attribute.Tower of decorators
@property @classmethod @abc.abstractmethod def PATTERN(cls): passThis can be very confusing to readers, as
@propertyand@classmethodnormally 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,parsewill 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 = NoneIf a concrete class fails to define its own
PATTERN,parsewill 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
PATTERNattribute.Other???