py_stepik/mod_oop/2.3_11_supershop.py

109 lines
3.3 KiB
Python
Raw Permalink Normal View History

2024-04-09 14:32:49 +00:00
# https://stepik.org/lesson/701985/step/11?unit=702086
from typing import Protocol
class Validator(Protocol):
def validate(self, value: str) -> bool:
...
class ValidatedField:
ValueValidator: Validator
def __init__(self, *args, **kwargs):
self.validator = self.ValueValidator(*args, **kwargs)
def __set_name__(self, owner, name):
self.name = "_" + name
def __get__(self, instance, owner):
return getattr(instance, self.name)
def __set__(self, instance, value):
if self.validator.validate(value):
setattr(instance, self.name, value)
class StringValue(ValidatedField):
class ValueValidator(Validator):
def __init__(self, min_length, max_length):
self.min_length, self.max_length = min_length, max_length
def validate(self, value: str) -> bool:
return (
isinstance(value, str)
and self.min_length <= len(value) <= self.max_length
)
class PriceValue(ValidatedField):
class ValueValidator(Validator):
def __init__(self, max_value):
self.max_value = max_value
def validate(self, value: str) -> bool:
return isinstance(value, int) and 0 <= value <= self.max_value
class Product:
name = StringValue(min_length=2, max_length=50)
price = PriceValue(max_value=10000)
def __init__(self, name, price):
self.name = name
self.price = price
class SuperShop:
def __init__(self, name):
self.name = name
self.goods: list[Product] = []
def add_product(self, product: Product):
self.goods.append(product)
def remove_product(self, product: Product):
self.goods.remove(product)
shop = SuperShop("У Балакирева")
shop.add_product(Product("Курс по Python", 0))
shop.add_product(Product("Курс по Python ООП", 2000))
for p in shop.goods:
print(f"{p.name}: {p.price}")
def tests():
shop = SuperShop("У Балакирева")
shop.add_product(Product("name", 100))
shop.add_product(Product("name", 100))
assert (
shop.name == "У Балакирева"
), "атрибут name объекта класса SuperShop содержит некорректное значение"
for p in shop.goods:
assert p.price == 100, "дескриптор price вернул неверное значение"
assert p.name == "name", "дескриптор name вернул неверное значение"
t = Product("name 123", 1000)
shop.add_product(t)
shop.remove_product(t)
assert (
len(shop.goods) == 2
), "неверное количество товаров: возможно некорректно работают методы add_product и remove_product"
assert hasattr(shop.goods[0], "name") and hasattr(shop.goods[0], "price")
t = Product(1000, "name 123")
if hasattr(t, "_name"):
assert type(t.name) == str, "типы поля name должнен быть str"
if hasattr(t, "_price"):
assert type(t.price) in (
int,
float,
), "тип поля price должнен быть int или float"
tests()