I'm trying to create a base class with a number of abstract python properties, in python 3.7.
I tried it one way (see 'start' below) using the @property, @abstractmethod, @property.setter annotations. This worked but it doesn't raise an exception if the subclass doesn't implement a setter. That's the point of using @abstract to me, so that's no good.
So I tried doing it another way (see 'end' below) using two @abstractmethod methods and a 'property()', which is not abstract itself but uses those methods. This approach generates an error when instantiating the subclass:
# {TypeError}Can't instantiate abstract class FirstStep with abstract methods end I'm clearly implementing the abstract methods, so I don't understand what it means. The 'end' property is not marked @abstract, but if I comment it out, it does run (but I don't get my property). I also added that test non-abstract method 'test_elapsed_time' to demonstrate I have the class structure and abstraction right (it works).
Any chance I'm doing something dumb, or is there some special behavior around property() that's causing this?
class ParentTask(Task): def get_first_step(self): # {TypeError}Can't instantiate abstract class FirstStep with abstract methods end return FirstStep(self) class Step(ABC): # __metaclass__ = ABCMeta def __init__(self, task): self.task = task # First approach. Works, but no warnings if don't implement setter in subclass @property @abstractmethod def start(self): pass @start.setter @abstractmethod def start(self, value): pass # Second approach. "This method for 'end' may look slight messier, but raises errors if not implemented. @abstractmethod def get_end(self): pass @abstractmethod def set_end(self, value): pass end = property(get_end, set_end) def test_elapsed_time(self): return self.get_end() - self.start class FirstStep(Step): @property def start(self): return self.task.start_dt # No warnings if this is commented out. @start.setter def start(self, value): self.task.start_dt = value def get_end(self): return self.task.end_dt def set_end(self, value): self.task.end_dt = value
starton 3.7.4 or 3.8.5. Simplified example with juststart, no*end, and an empty definition ofFirstStepraises I getTypeError: Can't instantiate abstract class FirstStep with abstract methods start. This has worked since 3.3.