py_stepik/mod_oop/3.1_11_dimensions.py
2024-04-10 16:00:37 +03:00

166 lines
7.7 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/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")]
[<class 'property'>, <class 'property'>, <class 'property'>]
При изменении значений __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()