class ColourComponent: def __init__(self, start, end): self.start = start self.end = end def __get__(self, instance, owner_class): # print(f'__get__ called') return int(instance.hex[self.start:self.end], 16) def __set__(self, instance, value): # print('__set__ called') pass class Colour: r = ColourComponent(1, 3) g = ColourComponent(3, 5) b = ColourComponent(5, 7) def __init__(self, hex): self.hex = hex def test_colour(): colour = Colour('#ff8823') print(colour.r) print(colour.g) print(colour.b) #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ class MaxLengthAttribute: def __get__(self, instance, owner_class): if instance.__dict__ == {}: return None return sorted(instance.__dict__.keys(), key= lambda x: (len(x), x), reverse=True)[0] class MyClass: max_length_attribute = MaxLengthAttribute() class JustClass: max_atr = MaxLengthAttribute() def test_len(): # obj = MyClass() # obj.name = "Vasiliy" # obj.city = "Saint Peterburg" # obj.country = "Rus" # print(obj.max_length_attribute) obj = JustClass() obj.mock = 15 obj.city = "Saint Peterburg" obj.name = "Vasiliy" obj.door = 'wood' print(obj.max_atr) #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ class RangeValidator: def __init__(self, start, end): self.start = start self.end = end self.value = 0 def __get__(self, instance, owner_class): pass def __set__(self, instance, value): if not isinstance(value, (int, float)): raise TypeError('Неправильный тип данных') if value < self.start or value > self.end: raise ValueError(f'Значение должно быть между {self.start} и {self.end}') self.value = value class Temperature: celsius = RangeValidator(-273.15, 1000) def test_range_validator(): temp = Temperature() try: temp.celsius = [1, 2] except TypeError as ex: print(ex) #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ class StringValidation: def __init__(self, min_length=None, max_length=None, exclude_chars=None, is_same_register=False): self.min_length = min_length self.max_length = max_length self.exclude_chars = exclude_chars self.is_same_register = is_same_register def __set_name__(self, owner_class, attribute_name): self.attribute_name = attribute_name def __set__(self, instance, value): if not isinstance(value, str): raise ValueError(f'В атрибут {self.attribute_name} можно сохранять только строки') if self.min_length is not None: if len(value) < self.min_length: raise ValueError(f'Длина атрибута {self.attribute_name} должна ' f'быть не меньше {self.min_length} символов') if self.max_length is not None: if len(value) > self.max_length: raise ValueError(f'Длина атрибута {self.attribute_name} должна ' f'быть не больше {self.max_length} символов') if self.exclude_chars is not None: for char in self.exclude_chars: if char in value: raise ValueError(f'Имеются недопустимые символы в атрибуте {self.attribute_name}') if self.is_same_register == True: if not value.isupper() and not value.islower(): raise ValueError(f'Все буквы должны быть в одном регистре в атрибуте {self.attribute_name}') instance.__dict__[self.attribute_name] = value def __get__(self, instance, owner_class): if instance is None: return self else: print(f'calling __get__ for {self.attribute_name}') return instance.__dict__.get(self.attribute_name, None) class Person: ''' name = StringValidation() last_name = StringValidation() ''' ''' name = StringValidation(min_length=10, exclude_chars='tyuio') last_name = StringValidation(max_length=5) ''' name = StringValidation(is_same_register=True, exclude_chars='tyur') last_name = StringValidation(max_length=10, is_same_register=True) def test_string_validation(): ''' p = Person() p.name = 'Michail' p.last_name = 'Lermontov' print(p.name, p.last_name) ''' ''' p = Person() try: p.name = 'Michail Second' except ValueError as ex: print(ex) try: p.last_name = 'Lermontov' except ValueError as ex: print(ex) print(p.name, p.last_name) ''' p = Person() try: p.name = 'Michail Second' except ValueError as ex: print(ex) try: p.last_name = 'LERMONTOV' except ValueError as ex: print(ex) print(p.name, p.last_name) #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ if __name__ == '__main__': # test_colour() # test_len() # test_range_validator() test_string_validation()