Но почему я не могу написать метод from_string так:
cls вместо явного
Date позволит наследнику
Date (напр.
AztecaDate - дата по календарю ацтеков) порождать именно
AztecaDate.
Кстати, есть одна тонкость, связанная с реализацией ООП на разных языках. C++ позволяет реализовать несколько разных, но одноимённых конструкторов класса с разной сигнатурой (набором аргументов), например, можно сделать так:
Date(1, 1, 2019) # конструктор с сигнатурой (int, int, int)
Date("1.1.2019") # другой конструктор с сигнатурой (str)
В питоне можно добиться подобного, но ручками, анализируя состав аргументов
Date.__init__, что неудобно, громоздко и нунафиг. Уж лучше забабахать
Date.from_string. Но это неизбежно в динамическом языке - ведь C++ должен знать всё про аргументы конкретных вызовов конструкторов на этапе компиляции, а мы можем в рантайм творить что угодно )))
для чего нужен staticmethod, если это уже не метод, а просто функция, и я могу вынести ее из класса.
Да, можете. Я думаю, тут действует логика лучшей читаемости и логика экономии пространства имён:
- Date._статикметод1 хоть и неочевидно что делает, но точно имеет отношение к Date
- При импорте
from date import *
вы не получите охапку непонятных имён.
Кстати, это не бесплатно - обращение к квалифицированному имени каждый раз создаёт дополнительный опкод
LOAD_ATTR. Поэтому любители выжать максимум производительности (ну бывает полезно в глубоком цикле) используют такой трюк:
# медленно
l = []
for i in range(100500):
l.append(i)
# чуть быстрее )))
push = l.append
for i in range(100500):
push(i)