py_stepik/mod_oop/3.4_11_box3d_math.py
2024-04-12 16:28:22 +03:00

122 lines
4.9 KiB
Python
Raw 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/701989/step/11?unit=702090
Объявите класс Box3D для представления прямоугольного параллелепипеда (бруска), объекты которого создаются командой:
box = Box3D(width, height, depth)
где width, height, depth - ширина, высота и глубина соответственно (числа: целые или вещественные)
В каждом объекте класса Box3D должны создаваться публичные атрибуты:
width, height, depth - ширина, высота и глубина соответственно.
С объектами класса Box3D должны выполняться следующие операторы:
box1 = Box3D(1, 2, 3)
box2 = Box3D(2, 4, 6)
box = box1 + box2 # Box3D: width=3, height=6, depth=9 (соответствующие размерности складываются)
box = box1 * 2 # Box3D: width=2, height=4, depth=6 (каждая размерность умножается на 2)
box = 3 * box2 # Box3D: width=6, height=12, depth=18
box = box2 - box1 # Box3D: width=1, height=2, depth=3 (соответствующие размерности вычитаются)
box = box1 // 2 # Box3D: width=0, height=1, depth=1 (соответствующие размерности целочисленно делятся на 2)
box = box2 % 3 # Box3D: width=2, height=1, depth=0
При каждой арифметической операции следует создавать новый объект класса Box3D с соответствующими значениями локальных атрибутов.
P.S. В программе достаточно только объявить класс Box3D. На экран ничего выводить не нужно.
"""
from operator import add, sub, mul, truediv, floordiv, mod, xor
def add_ops(*ops):
def decorator(cls):
def make_methods(op):
def method_new(self, other):
return self.__class__(*self.map_op(op, other))
def method_ip(self, other):
self.values = self.map_op(op, other)
return self
def method_r(self, other):
if isinstance(other, (int, float)):
return self.__class__(*map(lambda x: op(other, x), self.values))
return self.__class__(*map(op, other.values, self.values))
return {
f"__{op.__name__}__": method_new,
f"__i{op.__name__}__": method_ip,
f"__r{op.__name__}__": method_r,
}
for op in ops:
for name, method in make_methods(op).items():
setattr(cls, name, method)
return cls
return decorator
@add_ops(add, sub, mul, truediv, floordiv, xor, mod, pow)
class Box3D:
def __init__(self, width, height, depth):
self.width, self.height, self.depth = width, height, depth
@property
def values(self):
return self.width, self.height, self.depth
@values.setter
def values(self, values):
self.width, self.height, self.depth = values
def __repr__(self):
return f"{self.__class__.__name__}{self.values!r}"
def map_op(self, op, other):
if isinstance(other, (int, float)):
return map(lambda x: op(x, other), self.values)
return map(op, self.values, other.values)
def tests():
box1 = Box3D(1, 2, 3)
box2 = Box3D(2, 4, 6)
assert (
hasattr(box1, "depth") and hasattr(box1, "height") and hasattr(box1, "width")
), "ошибка в атрибутах"
box = box1 + box2
assert (
box.depth == 9 and box.height == 6 and box.width == 3
), "ошибка при операции Box3D(1, 2, 3) + Box3D(2, 4, 6)"
box1 = Box3D(1, 2, 3)
box = box1 * 2
assert (
box.depth == 6 and box.height == 4 and box.width == 2
), "ошибка при операции box1 * 2 (каждая размерность умножается на 2)"
box = 3 * box2
assert (
box.depth == 18 and box.height == 12 and box.width == 6
), "ошибка при операции 3 * box2"
box = box2 - box1
assert (
box.depth == 3 and box.height == 2 and box.width == 1
), "ошибка при операции box2 - box1"
box = box1 // 2
assert (
box.depth == 1 and box.height == 1 and box.width == 0
), "ошибка при операции box1 // 2"
box = box2 % 3
assert (
box.depth == 0 and box.height == 1 and box.width == 2
), "ошибка при операции box2 % 3"
if __name__ == "__main__":
import doctest
doctest.testmod()
tests()