2017-01-30 4 views
0

クラスを定義するときに、入力変数のタイプチェック(assertを使用)を含めるのが好きです。私は今、次のような抽象基底クラス(ABC)BaseRuleから継承する「専門的な」クラスRuleを定義しています:Pythonの抽象基本クラスに型チェックを組み込む方法

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に組み込みたいと思います。私はどうすればこれについて行くことができますか?

+0

とABC型注釈に、このドキュメントを参照してください。また、包括的なソリューションのために[MyPy](http://mypy-lang.org/)を見てみましょう。 – 9000

答えて

1

基本クラスに抽象的なゲッターメソッドとセッターメソッドを別々に呼び出す非抽象プロパティがあるようにします。プロパティは、セッターを呼び出す前に、必要な検証を実行できます。その他のコード(たとえば、派生クラスの__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 

あなたもBaseRuleRuleから__init__移動方法検討するかもしれませんこれは、Ruleの具体的な実装についての知識が必要ないためです。

+0

このスニペットにタイプミスがありますか?自分のコードを置き換えるために 'NameError:global name 'resource'が定義されていません。 –

+0

うん、はい、私は修正するために編集したタイプミス(値のリソースが '値のリソースのため 'だったはずです)がありました。それについて申し訳ありません! – Blckknght

関連する問題