166 lines
7.7 KiB
Python
166 lines
7.7 KiB
Python
|
"""
|
|||
|
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()
|