[英]Python override abstractmethod property setter and getter using decorators only
我正在嘗試創建一個抽象類,該類將強制實現同時實現 getter 和 setter。 我正在關注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
即使我在 B 中實現了foo
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):
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()
我知道有一種方法可以通過定義屬性而不使用裝飾器來做到這一點,就像這樣
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()
雖然這確實有效,但肯定有一種方法可以僅使用裝飾器來做到這一點,不是嗎?
我正在運行 python 3.4。
您的代碼引發異常,因為您在B.foo
方法上使用A.foo.setter
裝飾器,因此B.foo
方法實際上並未實現具有相同簽名的抽象方法A.foo
。
從裝飾器中刪除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 的定義放在兩個不同的類中,這在實際應用中可能不切實際。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.