TelenkovDmitry 6 meses atrás
pai
commit
a7fa5a6ca2

+ 127 - 3
courses/python_oop/descriptor/ex_1.py

@@ -37,8 +37,6 @@ class MaxLengthAttribute:
         return sorted(instance.__dict__.keys(), key= lambda x: (len(x), x), reverse=True)[0]
 
 
-
-
 class MyClass:
     max_length_attribute = MaxLengthAttribute()
 
@@ -61,7 +59,133 @@ def test_len():
     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_len()
+    # test_range_validator()
+    test_string_validation()
+    

+ 29 - 0
courses/python_oop/descriptor/ex_2.py

@@ -0,0 +1,29 @@
+
+class IntegerValue:
+    def __set__(self, instance, value):
+        print('__set__ called')
+
+    def __get__(self, instance, owner_class):
+        print('__get__ called')
+
+
+class Point:
+    x = IntegerValue()
+
+
+def test_1():
+    p = Point()
+    p.x = 100   # вызывает __set__ у дескриптора
+    p.x         # вызывает __get__ у дескриптора
+    print(p.__dict__)
+    p.__dict__['x'] = [10, 20, 30]
+    print(p.__dict__)
+    print(p.x)
+    p.x = 200
+    print(p.__dict__)
+
+def main():
+    test_1()
+
+if __name__ == '__main__':
+    main()

+ 66 - 0
courses/python_oop/descriptor/ex_3.py

@@ -0,0 +1,66 @@
+
+class CustomProperty:
+    def __init__(self, fget=None, fset=None):
+        self.fget = fget
+        self.fset = fset
+
+    def __set_name__(self, owner_class, prop_name):
+        self.prop_name = prop_name
+    
+    def __get__(self, instance, owner_class):
+        print('__get__ called...')
+        if instance is None:
+            return self
+        if self.fget is None:
+            raise AttributeError(f'{self.prop_name} is not readble.')
+        return self.fget(instance)
+    
+    def __set__(self, instance, value):
+        print('__set__ called...')
+        if self.fset is None:
+            raise AttributeError(f'{self.prop_name} is not writable.')
+        self.fset(instance, value)
+
+    def setter(self, fset):
+        self.fset = fset
+        return self
+    
+
+class Person:
+    @CustomProperty
+    def first_name(self):
+        return getattr(self, '_first_name', None)
+    
+    @first_name.setter
+    def first_name(self, value):
+        self._first_name = value
+
+    @CustomProperty
+    def last_name(self):
+        return getattr(self, '_last_name', None)
+    
+    @last_name.setter
+    def last_name(self, value):
+        self._last_name = value
+
+
+def test():
+    p = Person()
+    print(p.__dict__)
+    p.name = 'Artem'
+    print(p.name)
+    print(p.__dict__)
+
+    # пробуем затемнить дескриптор
+    p.__dict__['name'] = 'Egor'
+    print(p.name)
+
+
+
+def main():
+    test()
+
+
+if __name__ == '__main__':
+    main()
+