Init
init (сокращение от англ. initialization — инициализация) — программа в UNIX и Unix-подобных системах, которая запускает все остальные процессы. Работает как демон и обычно имеет PID 1. Обычно (согласно Filesystem Hierarchy Standard) располагается по пути /sbin/init.
Уровни инициализации
В процессе загрузки, после инициализации ядра, ядро запускает /sbin/init как первый процесс пользовательского режима. init отвечает за дальнейшую загрузку системы. Для этого он запускает так называемые стартовые скрипты, которые выполняют проверку и монтирование файловых систем, запуск необходимых демонов, настройку ядра (в том числе загрузку модулей ядра согласно установленному оборудованию, настройку IP-адресов, таблиц маршрутизации и др.), запуск графической оболочки и другие действия.
В операционных системах Unix/Linux с помощью init можно изменить уровень инициализации. Уровень инициализации — степень загрузки операционной системы. Вот как происходит инициализация системы: процесс init запускается и анализирует файл /etc/inittab. Следует отметить, что приведенная здесь система инициализации работает на системах Linux и Unix System V и она несколько отличается от стиля инициализации системы в BSD-подобных системах.
По умолчанию, в системе использовано 7 уровней инициализации:
0 — остановка системы
1 — загрузка в однопользовательском режиме
2 — загрузка в многопользовательском режиме без поддержки сети
3 — загрузка в многопользовательском режиме с поддержкой сети
4 — не используется
5 — загрузка в многопользовательском режиме с поддержкой сети и графического входа в систему
6 — перезагрузка
Набрав init n в терминале (с правами суперпользователя), где n — номер уровня инициализации, можно переключиться в любой из вышеперечисленных уровней.
Стартовые скрипты для каждого уровня находятся в каталогах с /etc/rc0.d до /etc/rc6.d, где цифра после rc соответствует номеру уровня инициализации.
Файл /etc/inittab
Как уже было упомянуто выше, работа процесса init управляется с помощью файла /etc/inittab. Вот пример этого файла (без комментариев):
id:5:initdefault: si::sysinit:/etc/rc.d/rc.sysinit l0:0:wait:/etc/rc.d/rc 0 l1:1:wait:/etc/rc.d/rc 1 l2:2:wait:/etc/rc.d/rc 2 l3:3:wait:/etc/rc.d/rc 3 l4:4:wait:/etc/rc.d/rc 4 l5:5:wait:/etc/rc.d/rc 5 l6:6:wait:/etc/rc.d/rc 6 1:2345:respawn:/sbin/mingetty tty1 2:2345:respawn:/sbin/mingetty tty2 3:2345:respawn:/sbin/mingetty tty3 4:2345:respawn:/sbin/mingetty tty4 5:2345:respawn:/sbin/mingetty tty5 6:2345:respawn:/sbin/mingetty tty6 x:5:respawn:/etc/X11/prefdm -nodaemon
В первой строке описан терминал и его конфигурация по умолчанию. Сначала в этом файле описываются уровни инициализации. Затем инициируются виртуальные консоли. Запись инициализации консолей состоит из полей, разделенных двоеточием и выглядит следующим образом:
- 1 — порядковый номер консоли
- 2345 — номера уровней инициализации, для которых консоль инициализируется
- respawn — этот параметр означает, что init должен перезапустить обслуживающий консоль процесс после выхода из сеанса или в случае краха.
- /sbin/mingetty tty6 — программа (с указанием параметров), которая будет обслуживать консоль.
Таким образом, вы легко можете создать свой уровень инициализации (под номером 4 или 7, 8…), просто исправив файл /etc/inittab и создав необходимые ссылки в каталоге /etc/rc.d/rc*.d
init в других ОС
В Windows NT роль init играет smss.exe. В Solaris 10 вместо init применяется Service Management Facility. /* init в Solaris 10 запускает и, в случае необходимости, перезапускает SMF (init initiates the core components of the service management facility, svc.configd(1M)and svc.startd(1M), and restarts these components if they fail). Т.е. можно сказать, что в Solaris 10 большая часть функций init выполняется с помощью SMF. */
Альтернативы init
Сейчас существует множество систем, призванных заменить собой классический init: Upstart, Runit, Daemontools, Launchd, Initng, systemd. Все они разрабатывались изначально для определенных дистрибутивов Linux или вообще для других систем.
Ссылки
- From Power Up To Bash Prompt (англ.)
- Системные и сервисные менеджеры
Инициализация и протоколы — Python: Введение в ООП
Теперь, когда вы знакомы со связанными методами, настало время рассказать про самый важный метод в Python: метод __init__ («dunder-init», «дандер инит»). Этот метод отвечает за инициализацию экземпляров класса после их создания.
На прошлых уроках Бобу — экземпляру класса Person , мы задавали имя уже после того, как сам объект был создан. Такое заполнение атрибутов объекта и выглядит громоздко и может приводить к разного рода ошибкам: объект может какое-то время находиться в «недозаполненном» (более общее название — «неконсистентном») состоянии. Инициализатор же позволяет получить уже полностью настроенный экземпляр.
Реализуем класс Person так, чтобы имя можно было указывать при создании объекта:
class Person: def __init__(self, name): self.name = name bob = Person('Bob') bob.name # 'Bob' alice = Person('Alice') alice.name # 'Alice'
Теперь нет нужды иметь в классе атрибут name = ‘Noname’ , ведь все объекты получают имена при инстанцировании!
Методы и протоколы
Вы заметили, что Python сам вызывает метод __init__ в нужный момент? Это же касается большинства dunder-методов: таковые вы только объявляете, но вручную не вызываете. Такое поведение часто называют протоколом (или поведением): класс реализует некий протокол, предоставляя нужные dunder-методы. А Python, в свою очередь, работает с объектом посредством протокола.
Продемонстрирую протокол получения длины имени объекта:
class Person: def __init__(self, name): self.name = name def __len__(self): return len(self.name) tom = Person('Thomas') len(tom) # 6
Я объявил метод dunder-len, и объекты класса Person научились возвращать «свою длину» (да, пример надуманный, но суть отражает). Вызов функции len на самом деле приводит к вызову метода __len__ у переданного в аргументе объекта!
Протоколы и «утиная типизация»
Существует такой термин: «утиная типизация» («duck typing») — «Если что-то крякает как утка и плавает как утка, то возможно это утка и есть!». Данный термин, пусть и звучит как шутка, описывает важный принцип построения абстракций: коду практически всегда достаточно знать о значении, с которым этот код работает, что это значение обладает нужными свойствами. Все остальное — не существенно.
Если коду достаточно знать, что сущность умеет плавать и крякать, то код не должен проверять сущность на фактическую принадлежность к уткам. Это позволит коду работать с робо-утками, даже если все настоящие утки вымрут, ведь код работает с абстрактными утками!
Открыть доступ
Курсы программирования для новичков и опытных разработчиков. Начните обучение бесплатно
- 130 курсов, 2000+ часов теории
- 1000 практических заданий в браузере
- 360 000 студентов
Наши выпускники работают в компаниях:
init в Python
Когда создается новый экземпляр класса в python, вызывается метод __init__, который оказывается очень хорошим местом, где мы можем изменить объект после его создания.
Это означает, что когда мы создаем новый экземпляр класса, например:
my_object = Student('Jetty')
Является ли __Init__ конструктором?
На самом деле да. __init__ — это конструкция oop. __init__ – это конструктор класса. Как упоминалось выше, метод __init__ вызывается, как только выделяется память для объекта. Посмотрим, что мы сделали выше в нашем фрагменте:
def __init__(self, something): self.something = something
Использование self важно, например:
def __init__(self, something): _something = something
Параметр something будет храниться в переменных в стеке и будет отброшен, как только метод __init__ выйдет за пределы области видимости.
Как __init__ работает с наследованием?
Когда у нас есть класс, наследующий от суперкласса, метод __init__ работает таким же образом. Давайте попробуем продемонстрировать, что происходит, когда мы пытаемся инициализировать дочерний класс:
class User(object): def __init__(self, something): print("User Init called.") self.something = something def method(self): return self.something class Student(User): def __init__(self, something): User.__init__(self, something) print("Student Init called.") self.something = something def method(self): return self.something my_object = Student('Jetty')
В приведенном выше коде, когда мы инициализировали объект Student, это будет результат, который создается при запуске указанной выше программы:

Итак, перед дочерним классом был вызван родительский класс init. Вы можете контролировать это, изменяя порядок, в котором init вызывается для родительского или дочернего класса.
Заключение
Подводя итог, __init__ в python – это то, что называется конструктором в других языках ООП, таких как C ++ и Java. Основная идея заключается в том, что это специальный метод, который автоматически вызывается при создании объекта этого класса.
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
- Программирование
