@Web__Nikita03

Зачем нужен @classmethod?

В интернете я нашел такой ответ:

Там представлен такой код:
class Date(object):

        def __init__(self, day=0, month=0, year=0):
            self.day = day
            self.month = month
            self.year = year

        (Собачка убрана)classmethod
        def from_string(cls, date_as_string):
            day, month, year = map(int, date_as_string.split('-'))
            date1 = cls(day, month, year)
            return date1

        (Собачка убрана)staticmethod
            def is_date_valid(date_as_string):
            day, month, year = map(int, date_as_string.split('-'))
            return day <= 31 and month <= 12 and year <= 3999

    date2 = Date.from_string('11-09-2012')
    is_date = Date.is_date_valid('11-09-2012')


Но почему я не могу написать метод from_string так:
@staticmethod
     def from_string(date_as_string):
        day, month, year = map(int, date_as_string.split('-'))
        date1 = Date(day, month, year)
        return date1


И для чего нужен staticmethod, если это уже не метод, а просто функция, и я могу вынести ее из класса.

Прошу сильно не бить ООП только начинаю изучать
  • Вопрос задан
  • 4146 просмотров
Решения вопроса 1
longclaps
@longclaps
Но почему я не могу написать метод 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)
Ответ написан
Пригласить эксперта
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Похожие вопросы