py_stepik/mod_oop/3.4_07_listmath.py
2024-04-12 14:16:47 +03:00

145 lines
5.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/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()