6 рекомендаций по определению метода __init__
Основным краеугольным камнем Python как объектно-ориентированного языка программирования является определение связанных классов для управления и обработки данных. Когда мы создаем класс, первым методом, который определяем является метод инициализации __init__ . Если вы примените следующие рекомендации, то тот, кто будет читать ваш код, лучше поймет механику работы всех объектов экземпляра класса. В этой статье я хочу рассказать вам о рекомендациях по определению метода __init__ .
1. Располагайте его в верхней части класса
Для большинства из нас эта рекомендация прозвучит очевидно, но я видел, как люди прячут его глубоко в теле класса вместе с другими атрибутами. Важно поместить его в самом начале, перед любыми другими методами. Именно здесь те, кто будут читать код, должны искать __init__ . Если у вас есть атрибуты, то метод __init__ следует поместить после них. Следовать этому правилу нужно для всех классов, которые вы пишете в своем проекте, чтобы читающие не путались.
2. Называйте первый параметр self
Прежде всего, вы должны понимать, за что отвечает первый параметр. Он относится к объекту экземпляра, который вызывает метод __init__ . Возможно, вы слышали термин «инстанцирование», однако метод __init__ сам по себе не эквивалентен ему. Как следует из названия, __init__ означает инициализацию, которая отвечает за процесс установки начального состояния созданного экземпляра класса. Есть соглашение, согласно которому первый параметр должен называться self , хотя это и не обязательно. Отмечу, что self – это не ключевое слово в Python, в отличие от многих других языков, где используется this , self или it . Они являются зарезервированными ключевыми словами для ссылки на текущий вызываемый экземпляр.
3. Задайте все атрибуты экземпляра
Python не ограничивает вас в месте определения атрибутов экземпляра класса. Однако это не значит, что вы можете писать их где угодно. Рассмотрим следующий пример:
class Student: def __init__(self, name): self.name = name def verify_registration(self): self.registered = True def get_guardian_name(self): self.guardian = "Someone"
Как показано выше, мы можем создать экземпляр класса Student , инициализировав его имя. Затем мы можем вызвать verify_registration , чтобы получить статус регистрации и get_guardian_name , чтобы получить информацию об опекуне учащегося. Однако так делать нежелательно, поскольку те, кто будут читать ваш код, не будут уверены в том, какие атрибуты есть у экземпляра. Вместо этого лучше поместить все атрибуты в __init__ , чтобы читатели точно знали, какие атрибуты есть у экземпляров. В следующей реализации шаблон гораздо лучше:
class Student: def __init__(self, name): self.name = name self.registered = False self.guardian = None
4. Старайтесь не использовать **kwargs
В Python **kwargs используется для указания различного числа именованных параметров в определениях функций. Таким образом синтаксически правильнее включать **kwargs в __init__ . Конечно, существуют обстоятельства, при которых использовать **kwargs в __init__ допустимо, но в большинстве случаев это не нужно, поскольку так вы маскируете необходимые параметры для инициализации экземпляров.Предполагаю, что одним из основных оправданий использования **kwargs является «чистота» __init__ . Однако я считаю, что явное всегда лучше, чем неявное. Несмотря на то, что перечисление всех параметров в заголовке метода __init__ может показаться громоздким, мы четко даем понять, какие параметры пользователю необходимо указать при создании экземпляров класса.
5. Устанавливайте правильные значения по умолчанию
Если вы знаете, какие начальные значения должны быть у определенных атрибутов, вы можете указать их в заголовке __init__ , чтобы пользователи не задавали эти параметры при создании экземпляров. В качестве альтернативы, если определенные значения применимы к большинству сценариев создания экземпляров, вы также можете задать эти параметры. Например:
class Student: def __init__(self, name, bus_rider=True): self.name = name self.bus_rider = bus_rider
Однако следует отметить, что, если параметр – это изменяемая структура данных, вам придется выбрать другой путь. Вот плохой пример:
class Student: def __init__(self, name, subjects=["maths", "physics"]): self.name = name self.subjects = subjects
Проблема в том, что, если вы указываете [“maths”, “physics”] как значение по умолчанию, этот список будет создан в определении функции и его же будут использовать все экземпляры. Вот как выглядит эта проблема:
>>> student0 = Student("John") >>> student0.subjects.append("music") >>> student0.subjects ['maths', 'physics', 'music'] >>> student1 = Student("Ashley") >>> student1.subjects ['maths', 'physics', 'music']
Документация
Как и в случае с другими методами, у __init__ тоже должна быть документация. Несмотря на то, что некоторым людям не нравится документировать информацию об архитектуре на уровне класса (то есть помещать информацию об инициализации под заголовком класса), все же рекомендуется размещать документацию прямо под методом __init__ . Для каждого параметра вы указываете его тип – будь то str или int . Исходя из этого, вы даете краткое описание того, что этот параметр из себя представляет и что он делает. Если есть значение по умолчание, расскажите о нем сопроводив доступным пояснением.
Заключение
Вот так выглядит список рекомендаций, которым я следую при определении метода __init__ для классов в Python. Лично я нахожу их полезными для поддержания читаемости кода. Если вам есть, что добавить, расскажите об этом в комментариях. Спасибо, что прочитали.
Материал подготовлен в рамках курса «Python Developer. Basic».
Всех желающих приглашаем на онлайн-интенсив «Мобильное приложение для автоматических рассылок с использованием Kivy Framework». За 2 дня интенсива мы создадим мобильное приложение (с использованием Kivy Framework) для планирования автоматических рассылок почтовых сообщений.
- python
- __init__
- метод __init__
- data science
- kivy framework
- создание мобильного приложения
- Блог компании OTUS
- Python
- Программирование
Зачем использовать __init__?
Переменные в классе при создании объекта будут иметь одно и то же значение, а при инициализации через конструктор ты можешь передавать разные значения.
Ответ написан более трёх лет назад
Комментировать
Нравится 1 Комментировать
- Это короче (File(«my.name») вместо x = File(); x.name = «myName»)
- Этим можно явно обозначить что некоторые параметры необходимы (нельзя создать файл без имени)
- Можно предпринять какие-то действия (например, открыть файл)
- Кстати, класс является callable — и вызывает конструктор при вызове себя: map(file, [«a.txt», «b.txt», «c.txt»])
Ответ написан более трёх лет назад
Комментировать
Нравится 1 Комментировать
Вячеслав @ShamanSBubnom
т.к. конструктор — это метод , он может не только присваивать значения полям , но и , например, вызывать функции.
Все зависит от задачи — если всегда нужно присваивать одни и те же значения , то конструктор действительно не нужен, а если что-то посложнее то без него никак.
Зачем нужен файл __init__.py?
Файл init.py играет важную роль в организации кода в пакетах Python и позволяет более эффективно структурировать вашу программу.
Он может содержать переменные, функции, классы и специальные методы, которые будут доступны при импортировании пакета, и определяет, какие модули будут импортированы при использовании символа ‘*’ в импорте. Без файла init.py пакет не будет распознан как таковой, поэтому этот файл является необходимым для создания пакетов в Python.
Допустим, у вас есть пакет «music» с файлами init.py, song.py и artist.py.
Файл init.py содержит следующий код:
from .song import Song from .artist import Artist __all__ = ['Song', 'Artist']
Теперь, если вы импортируете этот пакет и используете символ ‘*‘ для импорта всех элементов пакета, то будут импортированы только Song и Artist, так как именно эти модули определены в списке all в файле init.py:
from music import * my_song = Song('My Heart Will Go On', 'Celine Dion') my_artist = Artist('Celine Dion') my_song.play() my_artist.play_song(my_song)
Таким образом, файл init.py помогает определить, какие модули будут доступны при импортировании пакета и позволяет более гибко управлять импортом элементов пакета в вашем коде.
Разбираемся с __init__ и self в Python
Одни из основных концепций, которые новички встречают при изучении Python и особенно объектно-ориентированного программирования (ООП), это __init__ и self.
Алексей Кодов
Автор статьи
7 июля 2023 в 17:27
Одни из основных концепций, которые новички встречают при изучении Python и особенно объектно-ориентированного программирования (ООП), это __init__ и self . Это ключевые элементы классов в Python, понимание которых является важным шагом в освоении языка.
Пример проблемы
Допустим, есть класс, который описывает сущность «Автомобиль».
class Car: def __init__(self, color, brand): self.color = color self.brand = brand
Здесь видим две незнакомые конструкции: __init__ и self . Что они делают?
Разбор init
__init__ — это специальная функция, которая вызывается при создании нового объекта класса. Она также известна как конструктор класса. Это место, где обычно устанавливаются начальные значения атрибутов класса.
В примере выше, __init__ принимает три аргумента: self , color и brand . color и brand — это значения, которые передаются при создании нового объекта класса Car , и они устанавливаются в качестве атрибутов объекта.
my_car = Car('blue', 'Toyota')
В этом случае ‘blue’ и ‘Toyota’ передаются в __init__ и устанавливаются в качестве атрибутов color и brand для my_car .
Разбор self
self — это ссылка на текущий экземпляр класса. Это способ обращения к атрибутам и методам класса изнутри самого класса.
В примере выше, self.color = color устанавливает атрибут color текущего объекта класса Car в значение color , переданное в __init__ .
Следует отметить, что self не передается при создании нового объекта класса. Python автоматически передает ссылку на текущий объект в self .
my_car = Car('blue', 'Toyota') # self не передается
В заключение, __init__ и self являются важными концепциями в Python, особенно в контексте ООП. __init__ используется для инициализации новых объектов класса, а self — для ссылки на текущий объект класса.