[英]Python override abstractmethod property setter and getter using decorators only
I'm trying to create an abstract class that would force the implementation to implement both a getter and a setter.我正在尝试创建一个抽象类,该类将强制实现同时实现 getter 和 setter。 I'm following what is described at https://docs.python.org/3.4/library/abc.html#abc.abstractproperty but I keep getting
我正在关注https://docs.python.org/3.4/library/abc.html#abc.abstractproperty 中描述的内容,但我不断收到
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
even though I implement both foo
getter and setter in B.即使我在 B 中实现了
foo
getter 和 setter。
Here is my code:这是我的代码:
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):
def __init__(self, val):
self._foo = val
@property
def foo(self):
return self._foo
@A.foo.setter
def foo(self, val):
self._foo = val
if __name__ == '__main__':
test = B('bar')
test.do_stuff()
test.foo = 'barr'
test.do_stuff()
I know there is a way to do this by defining the property without using the decorator, like so我知道有一种方法可以通过定义属性而不使用装饰器来做到这一点,就像这样
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()
While this does work, there surely must be a way to do that with just the decorators, no?虽然这确实有效,但肯定有一种方法可以仅使用装饰器来做到这一点,不是吗?
I'm running python 3.4.我正在运行 python 3.4。
Your code raises an exception because you're using the A.foo.setter
decorator on the B.foo
method, so the B.foo
method does not actually implement the abstract method A.foo
with the same signature.您的代码引发异常,因为您在
B.foo
方法上使用A.foo.setter
装饰器,因此B.foo
方法实际上并未实现具有相同签名的抽象方法A.foo
。
Remove the A.
specification from the decorator, and your code would work:从装饰器中删除
A.
规范,您的代码将起作用:
@foo.setter
def foo(self, val):
self._foo = val
With the fix, you'll find that the class A
does enforce that the child classes implement both the getter and the setter for foo
(the exception you saw was actually a result of you not implementing the setter).通过修复,您会发现
A
类确实强制子类同时实现foo
的 getter 和 setter(您看到的异常实际上是您没有实现 setter 的结果)。
According to this issue you would need to go over an additional class in the hierarchy that implements solely the getter.根据此问题,您需要查看层次结构中仅实现 getter 的附加类。 The setter would then stay with the concrete class:
然后 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()
If you remove either the getter in B or the setter in C you will get the desired TypeError
exception.如果您删除 B 中的 getter 或 C 中的 setter,您将获得所需的
TypeError
异常。
This solution, however, forces you to put the definitions of getter and setter in two different classes, which might be impractical in real applications.但是,此解决方案迫使您将 getter 和 setter 的定义放在两个不同的类中,这在实际应用中可能不切实际。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.