Дескрипторы Python 2 со списком

66
5

Я хотел бы сделать некоторую проверку типов для значений, которые передаются в список.

До сих пор я делал некоторые дескрипторы, такие как 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))

Поэтому в конструкторе я передаю имя и value_type, которые должны быть уверены, что каждый элемент в списке должен иметь определенный тип.

Как я могу это сделать?

спросил(а) 2017-01-18T11:21:00+03:00 3 года, 5 месяцев назад
1
Решение
85

Благодаря вашим ответам и еще нескольким исследованиям я получил его на работу.

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)

В отличие от других полей, это можно переопределить без ошибки, но пока это будет сделано.

ответил(а) 2017-01-18T15:01:00+03:00 3 года, 5 месяцев назад
Ваш ответ
Введите минимум 50 символов
Чтобы , пожалуйста,
Выберите тему жалобы:

Другая проблема