From 8ca65819915a050971ea8aa7bbb2c7ce01e7a273 Mon Sep 17 00:00:00 2001 From: Dmitry Date: Fri, 12 Apr 2024 14:16:47 +0300 Subject: [PATCH] + 3.4_07 --- mod_oop/3.4_07_listmath.py | 144 +++++++++++++++++++++++++++++++++++++ 1 file changed, 144 insertions(+) create mode 100644 mod_oop/3.4_07_listmath.py diff --git a/mod_oop/3.4_07_listmath.py b/mod_oop/3.4_07_listmath.py new file mode 100644 index 0000000..8fe15ec --- /dev/null +++ b/mod_oop/3.4_07_listmath.py @@ -0,0 +1,144 @@ +""" + https://stepik.org/lesson/701989/step/7?unit=702090 + + Объявите класс с именем ListMath, объекты которого можно создавать командами: + +lst1 = ListMath() # пустой список +lst2 = ListMath([1, 2, -5, 7.68]) # список с начальными значениями +В качестве значений элементов списка объекты класса ListMath должны отбирать только целые и вещественные числа, остальные игнорировать (если указываются в списке). Например: + +lst = ListMath([1, "abc", -5, 7.68, True]) # ListMath: [1, -5, 7.68] +В каждом объекте класса ListMath должен быть публичный атрибут: + +lst_math - ссылка на текущий список объекта (для каждого объекта создается свой список). + +Также с объектами класса ListMath должны работать следующие операторы: + +lst = lst + 76 # сложение каждого числа списка с определенным числом +lst = 6.5 + lst # сложение каждого числа списка с определенным числом +lst += 76.7 # сложение каждого числа списка с определенным числом +lst = lst - 76 # вычитание из каждого числа списка определенного числа +lst = 7.0 - lst # вычитание из числа каждого числа списка +lst -= 76.3 +lst = lst * 5 # умножение каждого числа списка на указанное число (в данном случае на 5) +lst = 5 * lst # умножение каждого числа списка на указанное число (в данном случае на 5) +lst *= 5.54 +lst = lst / 13 # деление каждого числа списка на указанное число (в данном случае на 13) +lst = 3 / lst # деление числа на каждый элемент списка +lst /= 13.0 +При использовании бинарных операторов +, -, *, / должны формироваться новые объекты класса ListMath с новыми списками, прежние списки не меняются. + +При использовании операторов +=, -=, *=, /= значения должны меняться внутри списка текущего объекта (новый объект не создается). + +P.S. В программе достаточно только объявить класс. На экран ничего выводить не нужно. +""" + +from operator import add, sub, mul, truediv, floordiv, 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.lst_math = list(self.map_op(op, other)) + return self + + def method_r(self, other): + return self.__class__(map(lambda x: op(other, x), self.lst_math)) + + 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, pow) +class ListMath: + def __init__(self, lst_math=None): + self.lst_math = [*filter(lambda x: type(x) in (int, float), lst_math or [])] + + def __repr__(self): + return f"{self.__class__.__name__}({self.lst_math!r})" + + def map_op(self, op, other): + return map(lambda x: op(x, other), self.lst_math) + + +def tests(): + lst1 = ListMath() + lp = [1, False, 2, -5, "abc", 7] + lst2 = ListMath(lp) + lst3 = ListMath(lp) + + assert id(lst2.lst_math) != id( + lst3.lst_math + ), "внутри объектов класса ListMath должна создаваться копия списка" + + assert lst1.lst_math == [] and lst2.lst_math == [ + 1, + 2, + -5, + 7, + ], "неверные значения в списке объекта класса ListMath" + + res1 = lst2 + 76 + lst = ListMath([1, 2, 3]) + lst += 5 + assert lst.lst_math == [6, 7, 8] and res1.lst_math == [ + 77, + 78, + 71, + 83, + ], "неверные значения, полученные при операциях сложения" + + lst = ListMath([0, 1, 2]) + res3 = lst - 76 + res4 = 7 - lst + assert res3.lst_math == [-76, -75, -74] and res4.lst_math == [ + 7, + 6, + 5, + ], "неверные значения, полученные при операциях вычитания" + + lst -= 3 + assert lst.lst_math == [ + -3, + -2, + -1, + ], "неверные значения, полученные при операции вычитания -=" + + lst = ListMath([1, 2, 3]) + res5 = lst * 5 + res6 = 3 * lst + lst *= 4 + assert res5.lst_math == [5, 10, 15] and res6.lst_math == [ + 3, + 6, + 9, + ], "неверные значения, полученные при операциях умножения" + assert lst.lst_math == [ + 4, + 8, + 12, + ], "неверные значения, полученные при операциях умножения" + + lst = lst / 2 + lst /= 13.0 + + +if __name__ == "__main__": + import doctest + + doctest.testmod() + tests()