【发布时间】:2020-12-09 20:56:25
【问题描述】:
我正在尝试在 python 3.7 中创建一个具有许多抽象 python 属性的基类。
我使用@property、@abstractmethod、@property.setter 注释尝试了一种方法(参见下面的“开始”)。这有效,但如果子类没有实现 setter,它不会引发异常。这就是我使用@abstract 的意义所在,所以这不好。
所以我尝试使用两个@abstractmethod 方法和一个'property()' 以另一种方式(参见下面的'end'),它本身不是抽象的,而是使用这些方法。这种方法在实例化子类时会产生错误:
# {TypeError}Can't instantiate abstract class FirstStep with abstract methods end
我显然是在实现抽象方法,所以我不明白它的含义。 'end' 属性未标记为@abstract,但如果我将其注释掉,它会运行(但我没有得到我的属性)。我还添加了测试非抽象方法“test_elapsed_time”来证明我有正确的类结构和抽象(它有效)。
有没有可能我在做一些愚蠢的事情,或者 property() 周围有什么特殊行为导致了这种情况?
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
【问题讨论】:
-
我无法在 3.7.4 或 3.8.5 上使用
start重现您的问题。 Simplified example with juststart, no*end, and an empty definition ofFirstStepraises 我得到TypeError: Can't instantiate abstract class FirstStep with abstract methods start。这从 3.3 开始就有效。 -
哦,我明白了。您定义了一个 getter 但没有定义 setter,并且您希望同时需要 getter 和 setter。无视我。
-
是的@chepner 答案似乎解释了那部分。我还在努力消化剩下的。
标签: python python-3.x class oop abstract