Що таке __init__ у Python? [With Examples]

Хочете почати роботу з об’єктно-орієнтованим дизайном у Python? Зробіть перші кроки сьогодні, дізнавшись про метод __init__ Python.

У цьому посібнику ми розглянемо основи класів і об’єктів Python, а потім перейдемо до вивчення методу __init__.

До кінця цього підручника ви зможете відповісти на такі запитання:

  • Що таке змінні екземпляра або атрибути екземпляра?
  • Як метод init допомагає ініціалізувати атрибути екземпляра?
  • Як ми можемо встановити значення за замовчуванням для атрибутів?
  • Як ми можемо використовувати методи класу як конструктори для створення об’єктів?

Давайте розпочнемо.

Класи та об’єкти Python

Класи є фундаментальними для об’єктно-орієнтованого програмування на Python. Ми можемо створити клас і визначити атрибути та методи, щоб зв’язати разом дані та пов’язані функції.

Після того, як ми створили клас, ми можемо використовувати його як план (або шаблон) для створення об’єктів (екземплярів).

👩‍🏫Прикладний час! Давайте створимо клас Employee, де кожен об’єкт цього класу має такі атрибути:

  • full_name: повне ім’я співробітника у форматі firstName прізвище
  • emp_id: ідентифікатор працівника
  • відділ: відділ, до якого вони належать
  • досвід: кількість років досвіду, який вони мають

Що це значить? 🤔

Кожен окремий співробітник буде екземпляром або об’єктом класу Employee. І кожен об’єкт матиме власне значення для full_name, emp_id, department та experience.

Ці атрибути також називаються змінними екземплярів, і ми будемо використовувати терміни атрибути та змінні екземпляра як синоніми.

Трохи ми приступимо до додавання атрибутів. Зараз ми створюємо клас Employee таким чином:

class Employee:
    pass

Використання pass (як заповнювача) допомагає уникнути помилок під час запуску сценарію.

Хоча поточна версія класу Employee не дуже корисна, це все ще дійсний клас. Отже, ми можемо створювати об’єкти класу Employee:

employee_1 = Employee()

print(employee_1)
#Output: <__main__.Employee object at 0x00FEE7F0>

Ми також можемо додати атрибути та ініціалізувати їх значеннями, як показано:

employee_1.full_name="Amy Bell"
employee_1.department="HR"

Але такий підхід до додавання атрибутів екземпляра неефективний і схильний до помилок. Крім того, це не дозволяє використовувати клас як шаблон для створення об’єктів. Тут допоможе метод __init__.

Розуміння ролі методу __init__ у класі Python

Ми повинні мати можливість ініціалізувати змінні екземпляра під час створення екземпляра об’єкта, і метод __init__ допомагає нам це зробити. Метод __init__ викликається кожного разу, коли створюється новий об’єкт класу для ініціалізації значень змінних екземпляра.

  Виправте помилку Google Play Store під час перевірки оновлень

Якщо ви програмували на такій мові, як C++, ви побачите, що метод __init__ працює подібно до конструкторів.

Визначення методу __init__

Давайте додамо метод __init__ до класу Employee:

class Employee:
    def __init__(self, full_name,emp_id,department,experience):
        self.full_name = full_name
        self.emp_id = emp_id
        self.department = department
        self.experience = experience

Параметр self посилається на екземпляр класу, а self.attribute ініціалізує атрибут екземпляра значенням у правій частині.

Тепер ми можемо створювати такі об’єкти:

employee_2 = Employee('Bella Joy','M007','Marketing',3)
print(employee_2)
# Output: <__main__.Employee object at 0x017F88B0>

Коли ми друкуємо об’єкти службовців, ми не отримуємо жодної корисної інформації, окрім класу, до якого вони належать. Давайте додамо метод __repr__, який визначає рядок представлення для класу:

 def __repr__(self):
        return f"{self.full_name},{self.emp_id} from {self.department} with {self.experience} years of experience."

Додавши __repr__ до класу Employee, ми маємо:

class Employee:
    def __init__(self, full_name,emp_id,department,experience):
        self.full_name = full_name
        self.emp_id = emp_id
        self.department = department
        self.experience = experience
    
     def __repr__(self):
        return f"{self.full_name},{self.emp_id} from {self.department} with {self.experience} years of experience."

Тепер об’єкти службовців мають корисний рядок представлення:

print(employee_2)
# Output: Bella Joy,M007 from Marketing with 3 years of experience.

Деякі конвенції

Перш ніж продовжити, ось кілька приміток:

  • Ми використали self як перший параметр у методі __init__ для посилання на сам екземпляр класу та використали self.attribute_name для ініціалізації різних атрибутів. Рекомендовано використовувати self (ви можете використовувати будь-яку іншу назву).
  • Визначаючи метод __init__, ми встановлюємо імена параметрів у визначеннях __init__ відповідно до імен атрибутів. Це покращує читабельність.

Як додати значення за замовчуванням для атрибутів

У прикладі, який ми вже закодували, усі атрибути є обов’язковими. Це означає, що створення об’єкта буде успішним, лише якщо ми передамо значення для всіх полів у конструктор.

Спробуйте створити екземпляр об’єкта класу Employee, не передаючи значення для атрибута досвіду:

employee_3 = Employee('Jake Lee','E001','Engineering')

Ви отримаєте таку помилку:

Traceback (most recent call last):
  File "main.py", line 22, in <module>
    employee_3 = Employee('Jake Lee','E001','Engineering')
TypeError: __init__() missing 1 required positional argument: 'experience'

Але якщо ви хочете зробити певні атрибути необов’язковими, ви можете зробити це, вказавши значення за умовчанням для цих атрибутів під час визначення методу __init__.

Тут ми надаємо значення за замовчуванням 0 для атрибута досвіду:

class Employee:
    def __init__(self, full_name,emp_id,department,experience=0):
        self.full_name = full_name
        self.emp_id = emp_id
        self.department = department
        self.experience = experience
    
     def __repr__(self):
        return f"{self.full_name},{self.emp_id} from {self.department} with {self.experience} years of experience."

Об’єкт employee_3 створюється без значення для атрибута досвіду; стандартне значення 0 використовується для досвіду.

employee_3 = Employee('Jake Lee','E001','Engineering')
print(employee_3.experience)
# Output: 0

Альтернативні конструктори класу з використанням методів класу

Поки що ми лише бачили, як визначити метод __init__ і встановити значення за замовчуванням для атрибутів, коли це необхідно. Ми також знаємо, що нам потрібно передати значення для необхідних атрибутів у конструкторі.

  9 найкращих апаратних гаманців для криптовалют

Однак іноді значення для цих змінних екземпляра (або атрибутів) можуть бути доступні в іншій структурі даних, наприклад у кортежі, словнику або рядку JSON.

Так що ж нам робити?

Візьмемо приклад. Припустімо, що у нас є значення змінної екземпляра в словнику Python:

dict_fanny = {'name':'Fanny Walker','id':'H203','dept':'HR','exp':2}

Ми можемо зайти в словник і отримати всі атрибути так:

name = dict_fanny['name']
id = dict_fanny['id']
dept = dict_fanny['dept']
exp = dict_fanny['exp']

Після цього ви можете створити об’єкт, передавши ці значення в конструктор класу:

employee_4 = Employee(name, id, dept, exp)
print(employee_4)
# Output: Fanny Walker,H203 from HR with 2 years of experience.

Пам’ятайте: ви повинні робити це для кожного нового об’єкта, який ви створюєте. Такий підхід неефективний, і ми точно можемо зробити краще. Але як?

У Python ми можемо використовувати методи класу як конструктори для створення об’єктів класу. Щоб створити метод класу, ми використовуємо декоратор @classmethod.

Давайте визначимо метод, який аналізує словник, отримує значення змінної екземпляра та використовує їх для створення об’єктів Employee.

    @classmethod
    def from_dict(cls,data_dict):
        full_name = data_dict['name']
        emp_id = data_dict['id']
        department = data_dict['dept']
        experience = data_dict['exp']
        return cls(full_name, emp_id, department, experience)

Коли нам потрібно створити об’єкти, використовуючи дані зі словника, ми можемо використати метод класу from_dict().

💡 Зверніть увагу на використання cls у методі класу замість self. Так само, як ми використовуємо self для посилання на примірник, cls використовується для посилання на клас. Крім того, методи класу прив’язані до класу, а не до об’єктів.

Отже, коли ми викликаємо метод класу from_dict() для створення об’єктів, ми викликаємо його в класі Employee:

emp_dict = {'name':'Tia Bell','id':'S270','dept':'Sales','exp':3}
employee_5 = Employee.from_dict(emp_dict)
print(employee_5)
# Output: Tia Bell,S270 from Sales with 3 years of experience.

Тепер, якщо у нас є словник для кожного з n співробітників, ми можемо використовувати метод класу from_dict() як конструктор для створення екземплярів об’єктів — без необхідності отримувати значення миттєвих змінних зі словника.

📝Примітка щодо змінних класу

Тут ми визначили метод класу, який прив’язаний до класу, а не до окремих екземплярів. Подібно до методів класу, ми також можемо мати змінні класу.

  Як виправити, що OneNote не зберігає локальні резервні копії

Як і методи класу, змінні класу прив’язані до класу, а не до екземпляра. Коли атрибут приймає фіксоване значення для всіх екземплярів класу, ми можемо розглянути можливість визначення їх як змінних класу.

поширені запитання

1. Навіщо вам потрібен метод __init__ у Python?

Метод __init__ у визначенні класу дозволяє нам ініціалізувати атрибути або змінні екземплярів усіх екземплярів класу. Метод __init__ викликається кожного разу, коли створюється новий екземпляр класу.

2. Чи можна мати декілька методів __init__ у класі Python?

Метою наявності кількох методів __init__ у класі Python є надання кількох конструкторів, які створюють екземпляри об’єктів. Але ви не можете визначити кілька методів __init__. Якщо ви визначите кілька методів __init__, друга й остання реалізація перепишуть першу. Однак ви можете використовувати декоратор @classmethod для визначення методів класу, які можна використовувати як конструктори для створення екземплярів об’єктів.

3. Що станеться, якщо ви не визначите метод __init__ у класі?

Якщо ви не визначили метод __init__, ви все одно можете створювати екземпляри об’єктів. Однак вам доведеться вручну додати змінні екземпляра та призначити значення кожній із них. Ви не зможете передати значення для змінних екземплярів у конструкторі. Це не тільки схильне до помилок, але й перешкоджає меті мати клас як план, з якого ми можемо створювати екземпляри об’єктів.

4. Чи можете ви мати значення за замовчуванням для аргументів у методі __init__?

Так, під час визначення методу __init__ можна надати значення за замовчуванням для одного або кількох атрибутів. Надання значень за замовчуванням допомагає зробити ці атрибути необов’язковими в конструкторі. Атрибути приймають значення за замовчуванням, якщо ми не передаємо значення для цих атрибутів у конструкторі.

5. Чи можете ви змінювати атрибути за межами методу __init__?

Так, ви завжди можете оновити значення атрибута поза методом __init__. Ви також можете динамічно додавати нові атрибути до екземпляра після того, як ви створили конкретний екземпляр.

Висновок

У цьому посібнику ми навчилися використовувати метод __init__ для ініціалізації значень змінних екземплярів. Хоча це просто, воно може повторюватися, особливо коли у вас багато атрибутів.

Якщо вам цікаво, ви можете дослідити модуль класів даних. У Python 3.7 і новіших версіях ви можете використовувати вбудований модуль класів даних для створення класів даних, які зберігають дані. На додаток до реалізацій за замовчуванням __init__ та інших поширених методів; вони мають багато цікавих функцій для підказок типів, складних значень за замовчуванням і оптимізації.

Далі дізнайтеся більше про те, якщо __name__==’__main__’ у Python.