如何在 Python 中的抽象基础 class 中合并类型检查
How to incorporate type checking in an abstract base class in Python
当我定义 class 时,我喜欢包括输入变量的类型检查(使用 assert
)。我现在定义了一个'specialized' class Rule
继承自一个抽象基class (ABC) BaseRule
,类似如下:
import abc
class BaseRule(object):
__metaclass__ = abc.ABCMeta
@abc.abstractproperty
def resources(self):
pass
class Rule(BaseRule):
def __init__(self, resources):
assert all(isinstance(resource, Resource) for resource in resources) # type checking
self._resources = resources
@property
def resources(self):
return self._resources
class Resource(object):
def __init__(self, domain):
self.domain = domain
if __name__ == "__main__":
resources = [Resource("facebook.com")]
rule = Rule(resources)
Rule
__init__
函数中的 assert
语句 class 确保 resources
输入是列表(或其他可迭代的) Resource
个对象。但是,对于从 BaseRule
继承的其他 classes 也是如此,所以我想以某种方式将此断言合并到 abstractproperty
中。我该怎么做?
让你的基础 class 有一个 non-abstract 属性 调用单独的抽象 getter 和 setter 方法。 属性 可以在调用 setter 之前进行您想要的验证。其他想要触发验证的代码(例如派生 class 的 __init__
方法)可以通过 属性:
进行赋值来实现
class BaseRule(object):
__metaclass__ = abc.ABCMeta
@property
def resources(self): # this property isn't abstract and shouldn't be overridden
return self._get_resources()
@resources.setter
def resources(self, value):
assert all(isinstance(resource, Resources) for resource in value)
self._set_resources(value)
@abstractmethod
def _get_resources(self): # these methods should be, instead
pass
@abstractmethod
def _set_resources(self, value):
pass
class Rule(BaseRule):
def __init__(self, resources):
self.resources = resources # assign via the property to get type-checking!
def _get_resources(self):
return self._resources
def _set_resources(self, value):
self._resources = value
您甚至可以考虑将 __init__
方法从 Rule
移动到 BaseRule
class,因为它不需要任何关于 Rule
的知识的具体实现。
请参阅此文档,了解带有 mypy-lang https://mypy.readthedocs.io/en/latest/class_basics.html#abstract-base-classes-and-multiple-inheritance
的 abc 类型注释
当我定义 class 时,我喜欢包括输入变量的类型检查(使用 assert
)。我现在定义了一个'specialized' class Rule
继承自一个抽象基class (ABC) BaseRule
,类似如下:
import abc
class BaseRule(object):
__metaclass__ = abc.ABCMeta
@abc.abstractproperty
def resources(self):
pass
class Rule(BaseRule):
def __init__(self, resources):
assert all(isinstance(resource, Resource) for resource in resources) # type checking
self._resources = resources
@property
def resources(self):
return self._resources
class Resource(object):
def __init__(self, domain):
self.domain = domain
if __name__ == "__main__":
resources = [Resource("facebook.com")]
rule = Rule(resources)
Rule
__init__
函数中的 assert
语句 class 确保 resources
输入是列表(或其他可迭代的) Resource
个对象。但是,对于从 BaseRule
继承的其他 classes 也是如此,所以我想以某种方式将此断言合并到 abstractproperty
中。我该怎么做?
让你的基础 class 有一个 non-abstract 属性 调用单独的抽象 getter 和 setter 方法。 属性 可以在调用 setter 之前进行您想要的验证。其他想要触发验证的代码(例如派生 class 的 __init__
方法)可以通过 属性:
class BaseRule(object):
__metaclass__ = abc.ABCMeta
@property
def resources(self): # this property isn't abstract and shouldn't be overridden
return self._get_resources()
@resources.setter
def resources(self, value):
assert all(isinstance(resource, Resources) for resource in value)
self._set_resources(value)
@abstractmethod
def _get_resources(self): # these methods should be, instead
pass
@abstractmethod
def _set_resources(self, value):
pass
class Rule(BaseRule):
def __init__(self, resources):
self.resources = resources # assign via the property to get type-checking!
def _get_resources(self):
return self._resources
def _set_resources(self, value):
self._resources = value
您甚至可以考虑将 __init__
方法从 Rule
移动到 BaseRule
class,因为它不需要任何关于 Rule
的知识的具体实现。
请参阅此文档,了解带有 mypy-lang https://mypy.readthedocs.io/en/latest/class_basics.html#abstract-base-classes-and-multiple-inheritance
的 abc 类型注释