Различия между версиями 17 и 18
Версия 17 от 2017-11-20 09:05:27
Размер: 6416
Редактор: FrBrGeorge
Комментарий:
Версия 18 от 2017-11-25 21:08:04
Размер: 6415
Редактор: FrBrGeorge
Комментарий:
Удаления помечены так. Добавления помечены так.
Строка 48: Строка 48:
 * Базовые операции (типа `__add__()`), в т. ч. несуществующая `@` (`__mathmul__()`)  * Базовые операции (типа `__add__()`), в т. ч. несуществующая `@` (`__matmul__()`)

Классы и ООП

Разбор Д/З

ООП (предупреждение: не читайте Википедию, там частное вместо общего :( ):

  1. Инкапсуляция: иерархическое пространство объектов (как правило реализовано деревом пространства имён)

    • категоризация объектов
    • связь объекта и его namespace

    • механизм реализации наследования и полиморфизма
    • Python3 (и не только :) ): объект.поле

      • на самом деле это просто словари :)

  2. Наследование: повторное использование свойств объекта при создании нового (есть несколько путей: прототипирование, классы/подклассы, /?\ что ещё?)

    • описание только разницы между исходным и новым объектом

    • знание о предках и их свойствах (интроспекция)

      • ⇒ объектное планирование сложных и сверхсложных систем
    • Python3 (и не только): классы и подклассы
  3. Полиморфизм: повторное использование возможностей объекта при использовании принципиально другого объекта

    • реализация только разницы возможностей между исходным и новым объектом (во многих языках совпадает с механизмом наследования)

      • ⇒ объектное планирование сложных и сверхсложных систем
    • правила работы с отличающимися свойствами (например, то делать с дополнительными полями? много ещё чего)
    • Python3 (ещё примеры? Ruby?): параметрический полиморфизм, он же в данном случае Duck Typing: любой метод/функцию можно применять к любым объектам, лишь бы
      1. этот метод был,
      2. количество параметров было допустимым
      3. эти три правила были применимы к коду метода/функции

Спецметоды и перегрузка операций

Базовая статья: datamodel.html

Операций нет, а есть методы; операции — это

  • вызов метода, или
  • логика вызовов нескольких методов

Базовые функции

  • __dict__() :), примеры

  • __init__() / __del__() (Note: del x doesn’t directly call x.__del__())

  • __str__(),__repr__(),__bytes__()str(x)

  • __bool__(), __len__() — пустой ли?

  • __getattr__() / __getattribute__() / __setattr__() / __delattr__() / __dir__() — «.» и около

  • сравнения: __lt__(self, other), __le__(self, other), __eq__(self, other), __ne__(self, other), __gt__(self, other), __ge__(self, other)

    • Достаточно __lt__() и __le__()

Последовательности и прочие хранилища

  • __getitem__() / __setitem__() / __delitem__()/ __missing__()

  • __iter__()

  • __reversed__() или len() + getitem() — reversed(x)

  • __contains__()a in x

Числа

  • Базовые операции (типа __add__()), в т. ч. несуществующая @ (__matmul__())

  • Инкрементальные операции типа += (__iadd__())

  • Правые операции (__radd__()), их происхождение и протокол применения

    • "qwe"*3 vs. 3*"qwe" vs. "qwe".__mul__(3) vs. 3.__mul__("qwe") vs. "qwe".__rmul__(3)

  • Порождение новых объектов: c = a + b, какого типа c?

Возможности какие-то запредельные, если вдуматься

Д/З

  • Прочитать:
  • EJudge: SimpleVector 'Простой вектор'

    Определить класс Vector, работающий с трёхмерными векторами Вектора должны поддерживать:

    • Конструктор вектора из трёх вещественных чисел
    • Сложение и вычитание векторов A+B, A-B
    • Умножение и деление на число A*n, A/n; а также и n*A
    • Скалярное произведение A@B
    • Преобразование в строковый вид "x:y:z, где x, y и z — представление вещественного числа с двумя знаками после запятой (см. пример)
    Input:

    A = Vector(1,2,3)
    B = Vector(-1,3,-2)
    C = Vector(7,3,5)
    print("A, B, C:", A, B, C)
    print(A, "+", B, "=", A+B)
    print(A, "-", C, "=", A-C)
    print(A, "*", 2, "=", A*2)
    print(2, "*", B, "=", 2*B)
    print(C, "/", 3, "=", C/3)
    print(B, "@", C, "=", "{:.2f}".format(B@C))
    Output:

    A, B, C: 1.00:2.00:3.00 -1.00:3.00:-2.00 7.00:3.00:5.00
    1.00:2.00:3.00 + -1.00:3.00:-2.00 = 0.00:5.00:1.00
    1.00:2.00:3.00 - 7.00:3.00:5.00 = -6.00:-1.00:-2.00
    1.00:2.00:3.00 * 2 = 2.00:4.00:6.00
    2 * -1.00:3.00:-2.00 = -2.00:6.00:-4.00
    7.00:3.00:5.00 / 3 = 2.33:1.00:1.67
    -1.00:3.00:-2.00 @ 7.00:3.00:5.00 = -8.00
  • EJudge: StrangeDots 'Странные отрезки'

    Написать класс Dots, генерирующий заданное количество точек на заданом отрезке

    • При создании объекта типа Dots задаются вещественные границы отрезка

    Объект d типа Dots должен поддерживать индексирование по таким правилам:

    • d[n] — последовательность из n равноудалённых точек от начала до конца отрезка (включая конец)

    • d[i:n]i-я точка такой последовательности

    • d[i:j:n] — последовательность начиная с i-той и заканчивая j-1-й точкой такой последовательности

    • Выход за границы отрезка означает экстраполяцию (см. пример)
    Input:

    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])
    Output:

    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
  • EJudge: UnaryNumber 'Палочная система счисления'

    Написать класс Unary, реализующий единичную систему счисления. Палочное представление L числа N

    • создаётся из любой строки длиной N
    • представляется в виде строки из N символов "|"
    • имеет длину N
    • можно пройти циклом (при этом N раз возвращается палочная единица)
    • можно дополнить другим палочным числом K с помощью L |= K (при этом длина L увеличивается на длину K)

    • можно поделить пополам нацело с помощью ~L (лишняя палка исчезает)

    • можно дополнить одной палкой с помощью +L

    Во всех случаях изменения числа идентификатор объекта сохраняется. Унарныеоперации не только изменяют объект, но и возвращают его.

    Input:

       1 a = Unary("||")
       2 b = Unary("||||")
       3 print(a, b)
       4 a |= b
       5 print(a)
       6 print(~a)
       7 for c in a:
       8     print("  ",c)
       9     print(". ",+c)
      10     print("..",+c)
      11 ~a
      12 ~a
      13 print("Error" if a else a is a)
    
    Output:

    || ||||
    ||||||
    |||
       |
    .  ||
    .. |||
       |
    .  ||
    .. |||
       |
    .  ||
    .. |||
    True
  • EJudge: TrianglesCmp 'Сравниваем треугольники'

    Написать класс Triangle, моделирующий треугольник

    • объект T типа Triangle создаётся из трёх вещественных чисел — сторон треугольника

    • T пуст, если не выполняется строгое неравенство треугольника или хотя бы одна из сторон не положительна

    • abs(T) — площадь треугольника (0, если T пуст)

    • сравнение на неравенство двух объектов типа Triangle есть результат сравнения их площадей

    • два объекта S и T типа Triangle равны, если попарно равны их стороны (в некотором порядке)

    • строковое представление: a:b:c, где a, b и c — стороны треугольника в порядке их задания

    Input:

       1 Tri = Triangle(3,4,5), Triangle(5,4,3), Triangle(7,1,1), Triangle(5,5,5), Triangle(7,4,4)
       2 for a,b in zip(Tri[:-1],Tri[1:]):
       3     print(a if a else b)
       4     print("{}={:.2f} {}={:.2f}".format(a, abs(a), b, abs(b)))
       5     print(a == b)
       6     print(a >= b)
       7     print(a < b)
    
    Output:

    3.0:4.0:5.0
    3.0:4.0:5.0=6.00 5.0:4.0:3.0=6.00
    True
    True
    False
    5.0:4.0:3.0
    5.0:4.0:3.0=6.00 7.0:1.0:1.0=0.00
    False
    True
    False
    5.0:5.0:5.0
    7.0:1.0:1.0=0.00 5.0:5.0:5.0=10.83
    False
    False
    True
    5.0:5.0:5.0
    5.0:5.0:5.0=10.83 7.0:4.0:4.0=6.78
    False
    True
    False

LecturesCMC/PythonIntro2017/09_Overload (последним исправлял пользователь FrBrGeorge 2017-11-25 21:08:04)