""" https://stepik.org/lesson/701986/step/11?unit=702087 Объявите в программе класс Dimensions (габариты) с атрибутами: MIN_DIMENSION = 10 MAX_DIMENSION = 1000 >>> (Dimensions.MIN_DIMENSION, Dimensions.MAX_DIMENSION) (10, 1000) Каждый объект класса Dimensions должен создаваться командой: d3 = Dimensions(a, b, c) # a, b, c - габаритные размеры >>> d3 = Dimensions(10, 10, 10) и содержать локальные атрибуты: __a, __b, __c - габаритные размеры (целые или вещественные числа). Для работы с этими локальными атрибутами в классе Dimensions следует прописать следующие объекты-свойства: a, b, c - для изменения и считывания соответствующих локальных атрибутов __a, __b, __c. >>> (d3.a, d3.b, d3.c) (10, 10, 10) >>> [*map(lambda x: getattr(Dimensions, x).__class__, "abc")] [, , ] При изменении значений __a, __b, __c следует проверять, что присваиваемое значение число в диапазоне [MIN_DIMENSION; MAX_DIMENSION]. Если это не так, то новое значение не присваивается (игнорируется). С помощью магических методов данного занятия запретить создание локальных атрибутов MIN_DIMENSION и MAX_DIMENSION в объектах класса Dimensions. При попытке это сделать генерировать исключение: raise AttributeError("Менять атрибуты MIN_DIMENSION и MAX_DIMENSION запрещено.") >>> d3.MIN_DIMENSION = 4 Traceback (most recent call last): ... AttributeError: Менять атрибуты MIN_DIMENSION и MAX_DIMENSION запрещено. >>> d3.MAX_DIMENSION = 400 Traceback (most recent call last): ... AttributeError: Менять атрибуты MIN_DIMENSION и MAX_DIMENSION запрещено. Пример использования класса (эти строчки в программе писать не нужно): d = Dimensions(10.5, 20.1, 30) d.a = 8 d.b = 15 a, b, c = d.a, d.b, d.c # a=10.5, b=15, c=30 d.MAX_DIMENSION = 10 # исключение AttributeError >>> d = Dimensions(10.5, 20.1, 30) >>> d.a = 8 >>> d.b = 15 >>> (d.a, d.b, d.c) (10.5, 15, 30) P.S. В программе нужно объявить только класс Dimensions. На экран ничего выводить не нужно. """ def make_properties(*names): def decorator(cls): def prop(private_name: str): def getter(self): return getattr(self, private_name) def setter(self, value): return setattr(self, private_name, value) return getter, setter for name in names: setattr(cls, name, property(*prop(f"_{cls.__name__}__{name}"))) return cls return decorator @make_properties(*"abc") class Dimensions: MIN_DIMENSION = 10 MAX_DIMENSION = 1000 def __init__(self, a, b, c): self.a, self.b, self.c = a, b, c def __setattr__(self, name, value): if name in ["MIN_DIMENSION", "MAX_DIMENSION"]: raise AttributeError( "Менять атрибуты MIN_DIMENSION и MAX_DIMENSION запрещено." ) if not self.MIN_DIMENSION <= value <= self.MAX_DIMENSION: return super().__setattr__(name, value) def tests(): # из https://stepik.org/lesson/701986/step/11?discussion=7391213&unit=702087 # TEST-TASK___________________________________ x = Dimensions(10.0, 20, 30) # проверка что в классе прописаны объекты свойства a-b-c assert type(Dimensions.a) is property, "a - не является объектом свойством property" assert type(Dimensions.b) is property, "b - не является объектом свойством property" assert type(Dimensions.c) is property, "c - не является объектом свойством property" # проверка что в объекте класса существуют 3 приватных локальных атрибута assert ( "_Dimensions__a" in x.__dict__ and "_Dimensions__b" in x.__dict__ and "_Dimensions__c" in x.__dict__ ), "атрибуты не являются приватными" # проверка что данные считываются с приватных атрибутов assert ( x.a == 10.0 and x.b == 20 and x.c == 30 ), "при обращении к приватным атрибутам значения не получены проверьте объекты свойства" # проверка что значения являются целым или вещественным числами assert ( type(x.a) in (int, float) and type(x.b) in (int, float) and type(x.c) in (int, float) ), "значения должны быть или целым числом или вещественным" # проверка на существование атрибутов минимум-максимум assert hasattr(x, "MIN_DIMENSION"), "не найден атрибут MIN_DIMENSION" assert hasattr(x, "MAX_DIMENSION"), "не найден атрибут MAX_DIMENSION" # проверка что значение в диапазоне x.a = 9 assert ( x.a == 10.0 ), "присваиваемое значение должно быть в диапазоне [MIN_DIMENSION; MAX_DIMENSION]" x.b = -1 assert ( x.b == 20 ), "присваиваемое значение должно быть в диапазоне [MIN_DIMENSION; MAX_DIMENSION]" x.c = 1001 assert ( x.c == 30 ), "присваиваемое значение должно быть в диапазоне [MIN_DIMENSION; MAX_DIMENSION]" # проверка # С помощью магических методов данного занятия запретить создание локальных атрибутов MIN_DIMENSION и MAX_DIMENSION в объектах класса Dimensions. # При попытке это сделать генерировать исключение: # raise AttributeError("Менять атрибуты MIN_DIMENSION и MAX_DIMENSION запрещено.") try: x.MIN_DIMENSION = 0 except AttributeError: assert True else: assert False, "не сгенерировалось исключение AttributeError" try: x.MAX_DIMENSION = 0 except AttributeError: assert True else: assert False, "не сгенерировалось исключение AttributeError" assert ( "MIN_DIMENSION" not in x.__dict__ ), "запретить создание локальных атрибутов MIN_DIMENSION и MAX_DIMENSION в объектах класса Dimensions" assert ( "MAX_DIMENSION" not in x.__dict__ ), "запретить создание локальных атрибутов MIN_DIMENSION и MAX_DIMENSION в объектах класса Dimensions" if __name__ == "__main__": import doctest doctest.testmod() tests()