Python仅使用装饰器覆盖abstractmethod属性setter和getter
我试图创建一个抽象类,强制实现同时实现getter和setter。我一直在关注在上所描述的内容,但我一直在关注Python仅使用装饰器覆盖abstractmethod属性setter和getter,python,python-3.x,inheritance,abstract,Python,Python 3.x,Inheritance,Abstract,我试图创建一个抽象类,强制实现同时实现getter和setter。我一直在关注在上所描述的内容,但我一直在关注 Traceback (most recent call last): File "test.py", line 30, in <module> test = B('bar') TypeError: Can't instantiate abstract class B with abstract methods foo 我知道有一种方法可以做到这一点,即在不使用
Traceback (most recent call last):
File "test.py", line 30, in <module>
test = B('bar')
TypeError: Can't instantiate abstract class B with abstract methods foo
我知道有一种方法可以做到这一点,即在不使用decorator的情况下定义属性,就像这样
from abc import ABC, abstractmethod
class A(ABC):
@abstractmethod
def _get_foo(self):
pass
@abstractmethod
def _set_foo(self, val):
pass
def do_stuff(self):
print(self.foo)
foo = property(_get_foo, _set_foo)
class B(A):
def __init__(self, val):
self._foo = val
def _get_foo(self):
return self._foo
def _set_foo(self, val):
self._foo = val
foo = property(_get_foo, _set_foo)
if __name__ == '__main__':
test = B('bar')
test.do_stuff()
test.foo = 'barr'
test.do_stuff()
虽然这确实有效,但肯定有一种方法可以做到这一点,只有装饰师,不是吗
我正在运行Python3.4。您的代码引发了一个异常,因为您在
B.foo
方法上使用了A.foo.setter
装饰器,因此B.foo
方法实际上没有实现具有相同签名的抽象方法A.foo
从decorator中删除A.
规范,您的代码将正常工作:
@foo.setter
def foo(self, val):
self._foo = val
通过修复,您会发现类A
强制子类实现foo
的getter和setter(您看到的异常实际上是由于您没有实现setter).根据这一点,您需要检查层次结构中仅实现getter的附加类。然后,setter将继续使用混凝土类:
from abc import ABC, abstractmethod
class A(ABC):
@property
@abstractmethod
def foo(self):
pass
@foo.setter
@abstractmethod
def foo(self, val):
pass
def do_stuff(self):
print(self.foo)
class B(A):
_foo = None
@A.foo.getter
def foo(self):
return self._foo
class C(B):
def __init__(self, val):
self._foo = val
@B.foo.setter
def foo(self, val):
self._foo = val
if __name__ == '__main__':
test = C('bar')
test.do_stuff()
test.foo = 'barr'
test.do_stuff()
如果删除B中的getter或C中的setter,您将获得所需的TypeError
异常
但是,此解决方案迫使您将getter和setter的定义放在两个不同的类中,这在实际应用程序中可能是不切实际的。这里有两个不同的问题:代码中的错误(您使用了
@A.foo.setter
而不是@foo.setter
),以及创建抽象setter。据我所知,abc
模块不能强制您的子类实现可写属性。如果可能的话,把你的问题简化成这两个问题中的一个。哦,不能吗?这太糟糕了,听起来定义属性而不使用装饰符是一种方法。@HotCoffee:为什么要使用抽象方法?与java不同,在python中使用duck类型。我引用的python文档页面使用@C.x.setter
,因此我遵循了这个示例。我想医生是错的。顺便说一句,虽然这消除了错误,但它不会强制子类实现setter,这是在第一种情况下使用抽象方法的要点。如果我注释掉B
中的setter及其在\uuuu main\uuuu
中的用法,代码运行时不会出现任何错误,但我希望它抱怨B
没有实现抽象setter。
from abc import ABC, abstractmethod
class A(ABC):
@property
@abstractmethod
def foo(self):
pass
@foo.setter
@abstractmethod
def foo(self, val):
pass
def do_stuff(self):
print(self.foo)
class B(A):
_foo = None
@A.foo.getter
def foo(self):
return self._foo
class C(B):
def __init__(self, val):
self._foo = val
@B.foo.setter
def foo(self, val):
self._foo = val
if __name__ == '__main__':
test = C('bar')
test.do_stuff()
test.foo = 'barr'
test.do_stuff()