При правильном отступе вы не должны получать сообщение об ошибке, которое вы сообщаете:
class TripleString:
MIN_LEN = 1
MAX_LEN = 50
DEFAULT_STRING = "(undefined)"
def __init__(self, string1=DEFAULT_STRING, string2=DEFAULT_STRING,
string3=DEFAULT_STRING):
self.string1 = self.DEFAULT_STRING
self.string2 = self.DEFAULT_STRING
self.string3 = self.DEFAULT_STRING
self.set_string1(string1)
self.set_string2(string2)
self.set_string3(string3)
def set_string1(self, string1):
if self.valid_string(string1):
self.string1 = string1
return True
return False
def set_string2(self, string2):
if self.valid_string(string2):
self.string2 = string2
return True
return False
def set_string3(self, string3):
if self.valid_string(string3):
self.string3 = string3
return True
return False
def get_string1(self):
return self.string1
def get_string2(self):
return self.string2
def get_string3(self):
return self.string3
def to_string(self):
return self.string1 + ", " + self.string2 + ", " + self.string3
def valid_string(self, the_str):
if len(the_str) >= self.MIN_LEN and len(the_str) <= self.MAX_LEN:
return True
return False
Код можно написать более аккуратно, используя свойства:
class TripleString:
MIN_LEN = 1
MAX_LEN = 50
DEFAULT_STRING = "(undefined)"
@property
def string1(self):
return self._string1
@string1.setter:
def string1(self, value):
self._string1 = self._validate(value)
@property
def string2(self):
return self._string2
@string2.setter:
def string2(self, value):
self._string2 = self._validate(value)
@property
def string3(self):
return self._string3
@string3.setter:
def string3(self, value):
self._string3 = self._validate(value)
def __init__(self, string1=DEFAULT_STRING, string2=DEFAULT_STRING, string3=DEFAULT_STRING):
self.string1 = string1
self.string2 = string2
self.string3 = string3
def __str__(self):
return ", ".join([self.string1, self.string2, self.string3)]
def _validate(self, s):
if s is not None and self.MIN_LEN <= len(s) <= self.MAX_LEN:
return s
else:
return self.DEFAULT_STRING
Может быть реализованодаже больше чисто путем определения дескриптора, подобного пользовательскому свойству.
class StringProperty:
MIN_LEN = 1
MAX_LEN = 50
DEFAULT = "(undefined)"
def __init__(self):
self._d = {}
def __get__(self, obj, objtype=None):
if obj is None:
return self
return self._d[id(obj)]
def __set__(self, obj, value):
self._d[id(obj)] = self._validate(value)
def _validate(self, s):
if s is not None and self.MIN_LEN <= len(s) <= self.MAX_LEN:
return s
else:
return self.DEFAULT_STRING
class TripleString:
string1 = StringProperty()
string2 = StringProperty()
string3 = StringProperty()
def __init__(self, s1=None, s2=None, s3=None):
self.string1 = s1
self.string2 = s2
self.string3 = s3
Вся логика, связанная с проверкой такого свойства, инкапсулирована в классе StringProperty
.Словарь сопоставляет идентичность объекта, класс которого имеет атрибут StringProperty
, со значением свойства в этом объекте.Все назначения проверяются на месте.
>>> x = TripleString("foo", "bar")
>>> x.string1, x.string2, x.string3
('foo', 'bar', '(undefined)')
>>> x.string2 = 'baz'
>>> x.string2
'baz'
Доступ к значению x.string1
эквивалентен TripleString.string1.__get__(x)
, тогда как x.string2 = 'baz'
эквивалентен TripleString.string2.__set__(x, 'baz')
.