Объектная модель Python3
Долг за прошлый раз
Циклический конструктор генератора
1 >>> a=(i*2+1 for i in range(0,10,2) if i!=6)
2 >>> a
3 <generator object <genexpr> at 0x7feea8cd2938>
4 >>> next(a)
5 1
6 >>> next(a)
7 5
8 >>> next(a)
9 9
10 >>> next(a)
11 17
12 >>> next(a)
13 Traceback (most recent call last):
14 File "<stdin>", line 1, in <module>
15 StopIteration
16 >>> def fn(seq):
17 ... print(*seq)
18 ...
19 >>> fn((1,2,3))
20 1 2 3
21 >>> fn(i*2+1 for i in range(10) if i!=6)
22 1 3 5 7 9 11 15 17 19
23
При передаче такого генератора в качестве единственного параметра функции скобки можно убрать.
Параметрические декораторы
Статья на Хабре (это продолжение, можно почитать и предыдущие две)
Объектная модель Python3
Основная статья: первый скетч про классы
- Классы как пространства имён
- Классы как конструкторы объектов
Класс — callable()
- Поля класса и поля объектов, правила видимости
- Метод как функция в классе, видимая «сквозь» объект:
- Дополнительный первый параметр
- Обязательное использование имени объекта (точнее, связи с объектом) при обращении к его полю
__init__(), когда вызывается
- Заполнение полей объекта
Параметры __init__() и их передача
__del__(), когда вызывается (почитать тут)
isinstance()
Перегрузка операций
Базовая статья: special-method-names
Достаточно в классе определить соответствующие методы, и начинают работать len(), str() (и т. п.), а также всевозможные операции над экземплярами этого класса
__str__() и __repr()__
- Арифметические операции
- Протокол арифметической операции с учётом «правой» версии:
a+b → a.__add__(b)
Если возвращает специальный объект NotImplemented, но есть b.__radd__(), попробовать b.__radd__(a):
Прочие операции (сравнения, сдвиги, @ и т. д.)
Правые версии, версии для += и ему подобных
__getitem__(), __len___(), __iter__()
- …
Долги: __iter__, __del__, hasattr()/getattr()
Долг yield from
Д/З
Прочитать и прощёлкать 15-ю и 16-ю главы учебника
Прочитать про классы в tutorial; про «волшебные методы» например, тут
- В частности, прочесть про:
EJudge: SelfCount 'Сколько экземпляров?'
Написать класс we, содержащий поле count, в котором хранится информация о количестве существующих экземпляров этого класса.
a = we() print(a.count) b, c = we(), we(), print(a.count, b.count, c.count) del b print(a.count)
1 3 3 3 2
EJudge: DummyVec 'Что-то вроде вектора'
Написать класс vector, представляющий нечто, похожее на вектор. Должна поддерживаться операция вывода в формате, представленном в примере, конструирование из произвольной числовой последовательности ненулевой длины, а также сложение с числовой последовательностью такой же длины (в том числе с другим vector)
a, b = vector([2,1,2,1,2,1,2,1]), vector(range(8)) print(a, b, a+b, b+range(8), range(8)+b)
a, b = vector([2,1,2,1,2,1,2,1]), vector(range(8)) print(a, b, a+b, b+range(8), range(8)+b)
2:1:2:1:2:1:2:1 0:1:2:3:4:5:6:7 2:2:4:4:6:6:8:8 0:2:4:6:8:10:12:14 0:2:4:6:8:10:12:14
EJudge: StrangeDots 'Странные отрезки'
Написать класс Dots, генерирующий заданное количество точек на заданом отрезке
При создании объекта типа Dots задаются вещественные границы отрезка
Объект d типа Dots должен поддерживать индексирование по таким правилам:
d[n] — последовательность из n равноудалённых точек от начала до конца отрезка (включая конец)
d[i:n] — i-я точка такой последовательности
d[i:j:n] — последовательность начиная с i-той и заканчивая j-1-й точкой такой последовательности
- Выход за границы отрезка означает экстраполяцию (см. пример)
a = Dots(0,40) print(*a[5]) print(a[0:5]) print(a[2:5]) print(a[4:5]) print(a[7:5]) print(a[-7:5]) print(*a[1:3:5]) print(*a[:3:5]) print(*a[2::5]) print(*a[::5]) print(*a[-2:6:5])
0.0 10.0 20.0 30.0 40.0 0.0 20.0 40.0 70.0 -70.0 10.0 20.0 0.0 10.0 20.0 20.0 30.0 40.0 0.0 10.0 20.0 30.0 40.0 -20.0 -10.0 0.0 10.0 20.0 30.0 40.0 50.0