【问题标题】:How to incorporate type checking in an abstract base class in Python如何在 Python 的抽象基类中加入类型检查
【发布时间】:2017-01-30 16:15:15
【问题描述】:

当我定义一个类时,我喜欢包括输入变量的类型检查(使用assert)。我现在定义一个“专业”类Rule,它继承自抽象基类(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 语句确保resources 输入是Resource 对象的列表(或其他可迭代)。但是,从BaseRule 继承的其他类也是如此,所以我想以某种方式将此断言合并到abstractproperty 中。我该怎么办?

【问题讨论】:

  • 还可以查看MyPy 以获得全面的解决方案。

标签: python assert abc


【解决方案1】:

使您的基类具有一个非抽象属性,该属性调用单独的抽象 getter 和 setter 方法。该属性可以在调用 setter 之前进行您想要的验证。其他想要触发验证的代码(例如派生类的__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 类中,因为它不需要任何关于Rule 的具体实现的知识。

【讨论】:

  • 这个sn-p可能有错字吗?因为如果我用它来替换我的代码,我会得到NameError: global name 'resource' is not defined
  • 哎呀,是的,我确实有一个错字(for resources in value 应该是for resource in value),我现在已经对其进行了编辑以修复。很抱歉!
【解决方案2】:

【讨论】:

    猜你喜欢
    • 2016-05-28
    • 2018-11-06
    • 1970-01-01
    • 1970-01-01
    • 2011-12-16
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-07-11
    相关资源
    最近更新 更多