Терминология функций Python
Объясните пожалуйста проще эти понятия:
init - функция которая будет инициализировать/активировать свойства класса для определенного объекта, после создания и сопоставления с соответствующим классом.
self - представляет объект, который наследует эти свойства.
Для чего писать повторы self.month = month?
Ответы (1 шт):
Начать, думаю, стоит с того, что self используется, чтобы показать, что то, что идёт после него через ., – член класса. То есть просто month – обычная переменная, а self.month – атрибут класса.
Теперь о Вашем примере. Не буду долго распространяться про отдельный котёл в аду, который ждёт Вас за то, что код вставлен картинкой и мне теперь его руками надо переписывать вместо такого привычного Ctrl+C Ctrl+V... Итак, Вам просто попался такой пример, где не очень наглядно описывается, что данная конструкция не обязательно может быть такой. Во-первых, аргументы конструктора (те, что в скобках после __init__) отнюдь не обязаны иметь имена такие же, как у атрибутов класса (те, что после self.). Так что, для начала отмечу, что вот так тоже может быть:
class Date:
def __init__(self, mm, dd, yyyy):
self.month = mm
self.day = dd
self.year = yyyy
Здесь, как видите, уже нет никакого дублирования, а работать будет точно так же.
Теперь немного о том, что же там всё-таки происходит. Когда Вы создаёте объект Date, Вы передаёте ему три аргумента (первый – self – передаётся автоматически). Например today = Date(19, 3, 2021). Вот эти три аргумента передаются в метод __init__ Вашего только что созданного объекта today и становятся в нём аргументами mm, dd, yyyy соответственно. Потом они присваиваются атрибутам этого объекта соответственно self.month, self.day и self.year. То есть становятся свойствами объекта today и теперь Вы можете, вызвав print(today.year) узнать, какой сегодня год. Если бы этого присваивания не было, атрибуты self.month, self.day и self.year не были бы созданы и Вы так и остались бы в неведении насчёт года. Так что это не просто дублирование, это создание атрибутов и присваивание им значений из аргументов конструктора.
Теперь насчёт того, почему создатели языка не упростили эту конструкцию и заставляют нас присваивать все аргументы подряд атрибутам. На самом деле, мы можем сделать с этими аргументами что угодно или не делать с ними ничего. Например:
Не делать ничего (плохой пример, не стоит так делать):
# Вечно 2007ой
class Date:
def __init__(self, mm, dd, yyyy):
self.month = 1 # плевать мне на аргументы, мой класс, какие хочу значения у атрибутов, такие и задаю
self.day = 1
self.year = 2007
Делать что угодно (лучше что-то полезное):
class Date:
def __init__(self, mm, dd, yyyy):
if (mm < 1) or (mm > 12): # Например, проверка на корректность значений
print('Incorrect month')
return
self.month = mm
if (dd < 1) or (dd > 31):
print('Incorrect day')
return
self.day = dd
self.year = yyyy
Заключение – не стоит забывать, что __init__ – такой же метод класса, как остальные. Он так же принимает аргументы и может делать с ними что угодно. Конечно, классический и простой вариант – просто создание атрибутов и присваивание им значений из аргументов. Но этот вариант далеко не единственный. Вы можете совершить какие-то вычисления с этими аргументами и присвоить атрибутам результаты вычислений, можете передать аргументы базовому классу, можете создать ещё несколько объектов других классов, запустить что-то... В общем, что угодно на Ваше усмотрение.
P.S. Ну и, как обычно: это моё субъективное мнение, не претендующее на абсолютную истину, т.к. в Python я далеко не эксперт. Исправления и уточнения приветствуются в комментариях.
