py_stepik/mod_oop/3.5_06_dimensions_shopitem.py
2024-04-13 15:54:27 +03:00

187 lines
8.5 KiB
Python
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

"""
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"(6u1ZfY7keve3QIz92Lr3JPp<bYF9DAUz;kT?%Y-bYF9DE@5zRWo~3BQ)q8+NpxjxC@0Xm(6!LC(TgW6ATcm9G%O%QX>Db"
+ b"0b7^mGb0{=0EFd#5EFdv5Fexc13T$(9UvqFSVQ_F|Ze%D^Xm4;ybY*QQC(yUhzR<nVf+s8>H83zPGBhk8L}_hhZgXjGZgV"
+ b"IxFf1T4Ff1T7Fexc13T$(9UvqFSVQ_F|Ze%D^Xm4;ybY*QQC((t_zR<hSzR<MLxX`=NjL^N%xX`*MEFd&6FfcGIAVg_xWo"
+ b"~n6Z*FraGB7YOEFd;8Ff1T7Ffb`8DGF?JbYF9DE@5zRWo~3BQ)q8+NpxjxC@0Z^(6G?4(Sy-|(6!Nm(7MpDCoCW`FfcGKI"
+ b"XNsKL}_hhZgXjGZgVI#Ffc42GB7YKATls8DJdxm3T$(9UvqF@b8m8VWn>^dAX_KUx6r=Oz0ravEFdS)y3n=Iw9$(vEFdS*"
+ b"g3z$gvC)IkfY7zkg3!9quqP}aC((t_zR<hSzR<MLxX`=NjL^N%xX`*MT?%s`Js?|nE^c9MWgup6av*phX>K5Fb97&GXm4;"
+ b"|b8m8VWn^6nVRLh3a&#bUb97&Ga9?w8a&%>6AU!=Gb1Wbt(Sgvv(74fo(7w>RAZ&AVUvp@0a9?w8a&%>6Akl%*gwVdxfY7"
+ b"|qxY2;nzR<GJu+Y6A(7n*L(6Z3A(SXps(7qxH3S==LJs?DBZDnqAX>V?GC^RrEATuy5ATcs9DGFpVAUz;NX>Db0b7^mGb0"
+ b"{=0EFd#5EFdv5FewUTGax-6L}_hhZgXjGZgVIzFf1T4Ff1T3Ffb_!VRLh3a&#bMF(5oWAY?KuAR^Gc(6!LA(6!Nk(7n*UA"
+ b"ke<ig3*A`u+Xv4zR`lvu+Y08(7w>W(6!Nk(6G^h(7w@tAUr)H3So0|WpZ>NWHTT<Js@N<EFdD#z0kGLve32BfY80rz97)P"
+ b"(Sp%{(6G?4(7w@v(6G?EAke<hztFYOfY7kfg3!LvfFL|QA_`%1b7gXLAY?NjJRoE;EFdD#z0kGLve32BfY80rz97)P(Sp%"
+ b"{(6G?4(7w@v(6G?EAke<hztFYOfY7kfg3!LvfFL{~3JPR0E@2=&ATclsWHK&dAUz;4FbZTcE@L1)ATclsVRLh3a&#bMG9W"
+ b"x4WHBrtBGA3iwa~KAwb6jkz0kfO(7w@v(SXpf(6P|I(Sp#h(7PbezR<tWwb6jku+f6hzR`dnJRs1&(7w@u(7VvJAketbx6"
+ b"r)Mwa~rLwa~rLxY3Uw(7w>I(TdQu(7e#FAkl}=wb6jkwa~X9(7w>I(TdQu(7Mrr(Tgq7fzYzhzR<bRfzg7{ve2*~VJskGE"
+ b"Ffbd3I"
)
exec(b85decode(b))
if __name__ == "__main__":
import doctest
doctest.testmod()
tests()