2017-01-18 5 views
2

リストに渡される値の型チェックをしたいと思います。リスト付きのPython 2記述子

これまでCharFieldやIntegerFieldのようないくつかの記述子を作成しましたが、これは完全に機能します。

リスト記述子私は動作することができません。

ベースフィールドクラス:

class Field(object): 
    def __init__(self, type_, name, default=None, required=False): 
     self.type = type_ 
     self.name = "_" + name 
     self.required = required 
     self._default = default 

    def __get__(self, instance, owner): 
     return getattr(instance, self.name, self.default) 

    def __set__(self, instance, value): 
     raise NotImplementedError 

    def __delete__(self, instance): 
     raise AttributeError("Can't delete attribute") 

    @property 
    def default(self): 
     return self._default 

    @default.setter 
    def default(self, value): 
     self._default = value if value else self.type() 

マイCharFieldですクラス:

class CharField(Field): 
    def __init__(self, name, default=None, min_length=0, max_length=0, strip=False): 
     super(CharField, self).__init__(unicode, name, default=default) 
     self.min_length = min_length 
     self.max_length = max_length 
     self.strip = strip 

    def __set__(self, instance, value): 
     if not isinstance(value, (unicode, str)): 
      raise TypeError("{} must be a string or unicode".format(self.name)) 
     if self.strip: 
      value = value.strip() 
     if self.min_length and len(value) < self.min_length: 
      raise ValueError("{} must have a minimum length of {}".format(self.name, self.min_length)) 
     if self.max_length and len(value) > self.max_length: 
      raise ValueError("{} must have a maximum length of {}".format(self.name, self.max_length)) 
     setattr(instance, self.name, value) 

そしてListFieldをクラス:

class ListField(Field): 
    def __init__(self, name, value_type): 
     super(ListField, self).__init__(list, name, default=[]) 
     self.value_type = value_type 

    def __set__(self, instance, value): 
     if not isinstance(value, list): 
      raise TypeError("{} must be a list".format(self.name)) 
     setattr(instance, self.name, value) 

    def append(self, value): 
     if not isinstance(value, self.value_type): 
      raise ValueError("Value is list {} must be of type {}".format(self.name, self.value_type)) 

だから、コンストラクタで、私は名前であり、aを渡しますvalue_typeは、リスト内のすべての項目が特定のタイプであることを確認する必要があります。

どうすればいいですか?

+2

現在の実装で何が問題になっていますか? – hansaplast

+0

値リストの要素の型を 'isinstance(element、self.value_type)'コマンドで比較できますか?そうでない場合は、次のように追加することができます: 'すべてではない場合(要素内の要素に対してisinstance(element、self.value_type)):raise TypeError(" {要素の型は{} "でなければなりません。 @hansaplastリス​​トに値を追加するときにタイプチェックが機能しない – Frodon

+0

@ 1]) 'は動作しますが、' a.append(1) 'はエラーを発生させます –

答えて

0

ご回答いただき、ありがとうございました。他のフィールドとは異なり

class ListField(Field): 
    def __init__(self, name, value_type): 
     super(ListField, self).__init__(list, name, default=[]) 
     self.value_type = value_type 

    def __set__(self, instance, value): 
     if not isinstance(value, list): 
      raise TypeError("{} must be a list".format(self.name)) 
     setattr(instance, self.name, value) 

    def __iter__(self): 
     for item in self.default: 
      yield item 

    def __len__(self): 
     return len(self.default) 

    def __getitem__(self, item): 
     return self.default[item] 

    def append(self, value): 
     if not isinstance(value, self.value_type): 
      raise TypeError("Value is list {} must be of type {}".format(self.name, self.value_type)) 
     self.default.append(value) 

が、これはエラーがスローされずに上書きすることができますが、今のところこれが行います。

関連する問題