简体   繁体   English

如何在Python的抽象基类中合并类型检查

[英]How to incorporate type checking in an abstract base class in Python

When I define a class, I like to include type checking (using assert ) of the input variables. 当我定义一个类时,我喜欢包括输入变量的类型检查(使用assert )。 I am now defining a 'specialized' class Rule which inherits from an abstract base class (ABC) BaseRule , similar to the following: 我现在正在定义一个“特殊的”类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)

The assert statement in the __init__ function of the Rule class ensures that the resources input is a list (or other iterable) of Resource objects. Rule类的__init__函数中的assert语句可确保resources输入是Resource对象的列表(或其他可迭代的)。 However, this would also be the case for other classes which inherit from BaseRule , so I would like to incorporate this assertion in the abstractproperty somehow. 但是,对于其他继承自BaseRule类也是BaseRule ,因此我想以某种方式将此断言合并到abstractproperty How might I go about this? 我该怎么办?

Make your base class have a non-abstract property that calls separate abstract getter and setter methods. 使您的基类具有非抽象属性,该属性调用单独的抽象getter和setter方法。 The property can do the validation you want before calling the setter. 该属性可以在调用设置器之前进行所需的验证。 Other code (such as the __init__ method of a derived class) that wants to trigger the validation can do so by doing its assignment via the property: 想要触发验证的其他代码(例如派生类的__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

You might even consider moving the __init__ method from Rule into the BaseRule class, since it doesn't need any knowledge about Rule 's concrete implementation. 您甚至可以考虑将__init__方法从Rule移到BaseRule类中,因为它不需要任何有关Rule的具体实现的知识。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM