""" https://stepik.org/lesson/701990/step/6?unit=702091 Объявите класс Dimensions (габариты) с атрибутами: MIN_DIMENSION = 10 MAX_DIMENSION = 10000 >>> Dimensions.MIN_DIMENSION, Dimensions.MAX_DIMENSION (10, 10000) Каждый объект класса Dimensions должен создаваться командой: d3 = Dimensions(a, b, c) # a, b, c - габаритные размеры Значения a, b, c должны сохраняться в локальных приватных атрибутах __a, __b, __c объектах этого класса. >>> d3 = Dimensions(10, 20, 30) >>> d3._Dimensions__a, d3._Dimensions__b, d3._Dimensions__c (10, 20, 30) Для изменения и доступа к приватным атрибутам в классе Dimensions должны быть объявлены объекты-свойства (property) с именами: a, b, c. Причем, в момент присваивания нового значения должна выполняться проверка попадания числа в диапазон [MIN_DIMENSION; MAX_DIMENSION]. Если число не попадает, то оно игнорируется и существующее значение не меняется. >>> d3.a, d3.b, d3.c (10, 20, 30) >>> d3.a = 9; d3.a 10 С объектами класса Dimensions должны выполняться следующие операторы сравнения: dim1 >= dim2 # True, если объем dim1 больше или равен объему dim2 dim1 > dim2 # True, если объем dim1 больше объема dim2 dim1 <= dim2 # True, если объем dim1 меньше или равен объему dim2 dim1 < dim2 # True, если объем dim1 меньше объема dim2 >>> dim1, dim2, dim3 = Dimensions(10, 20, 30), Dimensions(20, 15, 20), Dimensions(10, 15, 35) >>> dim1 > dim3, dim1 == dim2, dim2 != dim3, dim3 < dim2, dim2 >= dim3 (True, True, True, True, True) Объявите в программе еще один класс с именем ShopItem (товар), объекты которого создаются командой: item = ShopItem(name, price, dim) где name - название товара (строка); price - цена товара (целое или вещественное число); dim - габариты товара (объект класса Dimensions). >>> item = ShopItem('Кеды', 1024, Dimensions(40, 30, 120)) В каждом объекте класса ShopItem должны создаваться локальные атрибуты: name - название товара; price - цена товара; dim - габариты товара (объект класса Dimensions). >>> item.name, item.price, item.dim ('Кеды', 1024, Dimensions(40, 30, 120)) Создайте список с именем lst_shop из четырех товаров со следующими данными: - кеды; 1024; (40, 30, 120) - зонт; 500.24; (10, 20, 50) - холодильник; 40000; (2000, 600, 500) - табуретка; 2000.99; (500, 200, 200) >>> lst_shop[:2] [ShopItem('кеды', 1024, Dimensions(40, 30, 120)), ShopItem('зонт', 500.24, Dimensions(10, 20, 50))] >>> lst_shop[2:] [ShopItem('холодильник', 40000, Dimensions(2000, 600, 500)), ShopItem('табуретка', 2000.99, Dimensions(500, 200, 200))] Сформируйте новый список lst_shop_sorted с упорядоченными по возрастанию объема (габаритов) товаров списка lst_shop, используя стандартную функцию sorted() языка Python и ее параметр key для настройки сортировки. Прежний список lst_shop должен оставаться без изменений. >>> lst_shop_sorted[:2] [ShopItem('зонт', 500.24, Dimensions(10, 20, 50)), ShopItem('кеды', 1024, Dimensions(40, 30, 120))] >>> lst_shop_sorted[2:] [ShopItem('табуретка', 2000.99, Dimensions(500, 200, 200)), ShopItem('холодильник', 40000, Dimensions(2000, 600, 500))] P.S. На экран в программе ничего выводить не нужно. """ from functools import total_ordering 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 @total_ordering @make_properties(*"abc") class Dimensions: MIN_DIMENSION = 10 MAX_DIMENSION = 10000 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) @property def volume(self): return self.a * self.b * self.c def __len__(self): return self.volume def __eq__(self, other): if isinstance(other, self.__class__): return self.volume == other.volume return NotImplemented def __lt__(self, other): if isinstance(other, self.__class__): return self.volume < other.volume return NotImplemented def __repr__(self): return f"{self.__class__.__name__}{(self.a, self.b, self.c)!r}" @total_ordering class ShopItem: def __init__(self, name, price, dim): self.name, self.price, self.dim = name, price, dim def __repr__(self): return f"{self.__class__.__name__}{(self.name, self.price, self.dim)!r}" def __eq__(self, other): if isinstance(other, self.__class__): return self.dim == other.dim return NotImplemented def __lt__(self, other): if isinstance(other, self.__class__): return self.dim < other.dim return NotImplemented data = [ ("кеды", 1024, (40, 30, 120)), ("зонт", 500.24, (10, 20, 50)), ("холодильник", 40000, (2000, 600, 500)), ("табуретка", 2000.99, (500, 200, 200)), ] lst_shop = [ShopItem(name, price, Dimensions(*dim)) for name, price, dim in data] lst_shop_sorted = sorted(lst_shop) def tests(): from base64 import b85decode b = ( b"VRLh3a&#bUWo{^Jb97&GXm4;SAU!=GG%O$@(TC8u(Sgvr(7qtijnKQ$wa~oKwa~rMg3!LuvLMj1AZ&AVUvp@0a3IjV" + b"(6u1ZfY7keve3QIz92Lr3JPpDb" + b"0b7^mGb0{=0EFd#5EFdv5Fexc13T$(9UvqFSVQ_F|Ze%D^Xm4;ybY*QQC(yUhzRH83zPGBhk8L}_hhZgXjGZgV" + b"IxFf1T4Ff1T7Fexc13T$(9UvqFSVQ_F|Ze%D^Xm4;ybY*QQC((t_zR^dAX_KUx6r=Oz0ravEFdS)y3n=Iw9$(vEFdS*" + b"g3z$gvC)IkfY7zkg3!9quqP}aC((t_zRK5Fb97&GXm4;" + b"|b8m8VWn^6nVRLh3a&#bUb97&Ga9?w8a&%>6AU!=Gb1Wbt(Sgvv(74fo(7w>RAZ&AVUvp@0a9?w8a&%>6Akl%*gwVdxfY7" + b"|qxY2;nzRV?GC^RrEATuy5ATcs9DGFpVAUz;NX>Db0b7^mGb0" + b"{=0EFd#5EFdv5FewUTGax-6L}_hhZgXjGZgVIzFf1T4Ff1T3Ffb_!VRLh3a&#bMF(5oWAY?KuAR^Gc(6!LA(6!Nk(7n*UA" + b"keW(6!Nk(6G^h(7w@tAUr)H3So0|WpZ>NWHTTI(TdQu(7e#FAkl}=wb6jkwa~X9(7w>I(TdQu(7Mrr(Tgq7fzYzhzR