[英]Python abstract setters and getters
我想編寫摘要 class,它將強制繼承類來實現我的摘要 class 中的所有方法和屬性。
此外,我想為我的抽象屬性使用 setter 和 getter 以使我的代碼整潔且看起來不錯
但是,當前的實現:
import abc
class Component(metaclass=abc.ABCMeta):
@property
@abc.abstractmethod
def status(self):
pass
@property
@status.setter
@abc.abstractmethod
def status(self, value):
pass
強制繼承 class 為我的抽象屬性 getter 實現 getter,但不強制創建屬性 setter(這正是我想要的)
如何在不失去應用進一步提到的方法(也就是編寫新方法並在我的抽象 class setter 中執行它們)的所有好處的情況下實現此行為?
從 abc 導入 ABCMeta,抽象方法
類基(對象):元類= ABCMeta
def __init__(self, val):
self._foo = val
@abstractmethod
def _doStuff(self, signals):
print ('Base does stuff')
@abstractmethod
def _get_foo(self):
return self._foo
@abstractmethod
def _set_foo(self, val):
self._foo = val + 'r'
foo = property(_get_foo, _set_foo)
class floor_1(Base):元類= ABCMeta
def __init__(self, val):
self._foo = val
super(floor_1, self).__init__(val)
def _doStuff(self, signals):
print ('floor_1 does stuff')
def _get_foo(self):
return self._foo
def _set_foo(self, val):
#self._foo = val + 'r'
super()._set_foo(val + 'r')
foo = property(_get_foo, _set_foo)
班級 floor_2(floor_1):
@property
def foo(self):
return self._foo
@foo.setter
def foo(self, val):
self._foo = val + 'r'
#super()._set_foo(val + 'r')
b1 = floor_1('bar')
打印(b1.foo)b1.foo = 'bar' 打印(b1.foo)
問題是getter和setter都不是你抽象的方法class; 它們是 property 的屬性,它是一個(不可調用的)class 屬性。 考慮這個等價的定義:
def status_getter(self):
pass
def status_setter(self, value):
pass
class Component(metaclass=abc.ABCMeta):
# status = property(...)
# status.__isabstractmethod__ = True
status = abstractmethod(property(status_getter, status_setter))
繼承屬性與繼承方法完全不同。 您基本上是在替換該屬性,因為您的 class 本身沒有對 getter 或 setter 的引用。 盡管名稱如此, abstractmethod
實際上並沒有使屬性成為方法; 它實際上無非是向應用它的任何對象添加一個屬性並返回原始值。
那么,要確保子類提供讀/寫屬性,您要做什么? 跳過裝飾器語法,將 getter 和 setter 定義為顯式抽象方法,然后根據這些私有方法顯式定義屬性。
class Component(metaclass=abc.ABCMeta):
@abstractmethod
def _get_status(self):
pass
@abstractmethod
def _set_status(self, v):
pass
status = property(lambda self: self._get_status(), lambda self, v: self._set_status(self, v))
或者,您可以使用__init_subclass__
(它晚於abc
;其目的是允許 class 初始化,否則只能通過元類進行初始化)。
class Component:
def __init_subclass(cls, **kwargs):
super().__init_subclass__(**kwargs)
try:
p = cls.status
except AttributeError:
raise ValueError("Class does not define 'status' attribute")
if not isinstance(p, property):
raise ValueError("'status' is not a property")
if p.fget is None:
raise ValueError("'status' has no getter")
if p.fset is None:
raise ValueError("'status' has no setter")
在我看來,這實際上是對abc
的改進。 如果子類未能定義讀/寫status
屬性,則在定義class 時將引發異常,而不僅僅是在您嘗試實例化 class 時。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.