py_stepik/mod_oop/3.4_07_listmath.py

145 lines
5.9 KiB
Python
Raw Permalink Normal View History

2024-04-12 11:16:47 +00:00
"""
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()