145 lines
5.9 KiB
Python
145 lines
5.9 KiB
Python
"""
|
||
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()
|