Терминология функций Python

Объясните пожалуйста проще эти понятия:

init - функция которая будет инициализировать/активировать свойства класса для определенного объекта, после создания и сопоставления с соответствующим классом.

self - представляет объект, который наследует эти свойства.

Для чего писать повторы self.month = month?

введите сюда описание изображения


Ответы (1 шт):

Автор решения: V-Mor

Начать, думаю, стоит с того, что 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 я далеко не эксперт. Исправления и уточнения приветствуются в комментариях.

→ Ссылка