Перейти к содержимому
На этой странице

ООП. Классы и методы

Все темы Python Developer

Какие типы классов существуют в Python?

В Python 3 все классы наследуют object прямо или косвенно. Классы старого стиля относятся только к Python 2; метаклассы выполняют отдельную роль, создавая классы.

Новые стили классов (New-style classes):

  • Это классы, которые являются наследниками встроенного класса object.

  • В Python 3.x все классы автоматически являются новыми стилями.

Старые стили классов (Old-style classes):

  • Это классы, которые не являются наследниками класса object.

  • В Python 2.x классы старого стиля создавались без явного указания наследования от object.

Метаклассы (Metaclasses):

  • Это классы, экземпляры которых являются классами.

  • Они используются для управления созданием классов и их поведением.

  • Метаклассы часто используются для магического манипулирования атрибутами и методами классов.

В Python 3 классов старого стиля нет. Метаклассом по умолчанию служит type.


Что представляют собой “магические” методы в Python и какие виды магических методов существуют?

“Магические” методы в Python представляют собой специальные методы с двойными подчеркиваниями в начале и в конце своего имени. Они позволяют определить поведение объектов в различных ситуациях, таких как итерация, вызов функций, доступ к атрибутам и т. д. Некоторые из наиболее часто используемых магических методов включают __init__ для инициализации объекта, __str__ для представления объекта в виде строки, __len__ для определения длины объекта и многие другие.


В чем разница между методами __init__() и __str__()?

Метод __init__() используется для инициализации нового объекта в классе. Он вызывается автоматически при создании экземпляра класса и используется для инициализации атрибутов объекта.

Метод __str__() используется для представления объекта в виде строки. Он вызывается при использовании функции str() или при преобразовании объекта в строку, например, при вызове print().


Что представляют собой геттеры и сеттеры?

Геттеры и сеттеры - это методы, используемые для доступа к атрибутам объекта.

Геттеры (getters):

  • Геттеры позволяют получать значение атрибута объекта.

  • Они обычно используются для получения значения приватных атрибутов.

  • Геттеры обеспечивают контролируемый доступ к данным объекта.

Сеттеры (setters):

  • Сеттеры позволяют устанавливать значение атрибута объекта.

  • Они используются для установки значения атрибута с дополнительной проверкой или обработкой.

  • Сеттеры обеспечивают контролируемое изменение данных объекта.

Использование геттеров и сеттеров помогает обеспечить инкапсуляцию данных и контролировать доступ к ним в объектно-ориентированном программировании.


Как сделать неизменяемый класс в Python?

Чтобы создать неизменяемый класс в Python, следует:
  1. Определить класс с помощью ключевого слова class.

  2. Использовать неизменяемые значения полей. Двойное подчёркивание меняет имя атрибута, но не запрещает его изменение.

  3. Создать методы только для чтения атрибутов класса (без методов для изменения значений).

  4. Переопределить методы __setattr__() и __delattr__(), чтобы они возбуждали исключение AttributeError, предотвращая изменение атрибутов класса.

  5. По желанию, переопределить метод __hash__(), если класс будет использоваться в качестве ключа в словарях или множествах.

Пример:
class ImmutableClass:
    def __init__(self, value):
        object.__setattr__(self, "_ImmutableClass__value", value)

    @property
    def value(self):
        return self.__value

    def __setattr__(self, name, value):
        raise AttributeError("ImmutableClass object does not support attribute assignment")

    def __delattr__(self, name):
        raise AttributeError("ImmutableClass object does not support attribute deletion")

    def __hash__(self):
        return hash(self.__value)

Что считается объектом в ООП?

В объектно-ориентированном программировании (ООП), объект представляет собой экземпляр класса. Он содержит данные (атрибуты) и методы, которые оперируют этими данными. Объекты могут взаимодействовать друг с другом, отправляя сообщения (вызывая методы) и обмениваясь данными. Класс определяет структуру (атрибуты) и поведение (методы) объектов, а объекты являются конкретными экземплярами класса, обладающими конкретными значениями данных.


Является ли функция объектом в Python?

Да, в Python функция является объектом первого класса, что означает, что она может быть присвоена переменной, передана как аргумент в функцию, возвращена из другой функции и т. д. Функции в Python могут быть созданы и использованы так же, как и любые другие объекты данных.


Какой класс может создавать другие классы в Python?

В Python класс, который создает другие классы, называется метаклассом. Метаклассы представляют собой специальные классы, экземпляры которых сами являются классами. Они управляют созданием, поведением и структурой других классов. Метаклассы обычно используются для изменения поведения классов, добавления магических методов или управления созданием экземпляров классов.


Какой самый первый метакласс в Python?

В Python самый первый метакласс, который управляет созданием всех классов по умолчанию, называется type. Когда вы определяете новый класс в Python, интерпретатор автоматически использует метакласс type для создания этого класса.


Как MRO определяет поиск методов в Python?

MRO задает линейный порядок, в котором класс и его базовые классы ищут атрибуты. Python строит его алгоритмом C3, сохраняя локальный порядок родителей и согласованность иерархии; несовместимая схема классов не создастся. Порядок виден в Cls.__mro__ или Cls.mro(). super() обращается к следующему классу именно в MRO, поэтому кооперативные методы должны принимать совместимые аргументы и вызывать super(). Механизм применяют ради ясного контракта объекта, а не как способ скрыть обычную функцию или простые данные.


Когда использовать dataclass вместо обычного класса?

dataclass подходит классу, который в основном хранит типизированные поля: он генерирует __init__, __repr__, сравнение и другие методы по параметрам. Для изменяемого значения по умолчанию используют field(default_factory=...). frozen=True запрещает обычное присваивание, но не превращает вложенные объекты в глубоко неизменяемые. При сложных инвариантах и богатом поведении явный класс часто читается лучше, хотя __post_init__ может выполнять локальную проверку. Механизм применяют ради ясного контракта объекта, а не как способ скрыть обычную функцию или простые данные.


Что меняет __slots__ в Python-классе?

__slots__ объявляет допустимые атрибуты и обычно убирает отдельный __dict__ у каждого экземпляра, экономя память при большом числе объектов. Динамически добавить произвольное поле тогда нельзя. Для слабых ссылок нужен слот __weakref__; наследование требует аккуратно объявлять слоты на каждом уровне. Это оптимизация представления экземпляров, а не механизм приватности, и выгоду следует измерять на реальной модели. Механизм применяют ради ясного контракта объекта, а не как способ скрыть обычную функцию или простые данные.


Чем __new__ отличается от __init__?

__new__ создает и возвращает экземпляр, получая класс первым аргументом. Если он вернул экземпляр этого класса, Python затем вызывает __init__, который настраивает уже созданный объект и должен вернуть None. __new__ переопределяют для immutable-типов, кэширования или контроля создания. Если он вернул объект другого типа, __init__ исходного класса обычно не вызывается. Механизм применяют ради ясного контракта объекта, а не как способ скрыть обычную функцию или простые данные.


Когда применять @property?

@property сохраняет интерфейс обычного атрибута, добавляя вычисление, проверку или управляемую запись. Getter должен оставаться недорогим и не удивлять заметным I/O. Setter полезен для локального инварианта, но сложную бизнес-операцию лучше назвать методом. Property позволяет позже изменить внутреннее хранение без смены вызовов, однако не превращает публичный атрибут в настоящую защиту от доступа. Механизм применяют ради ясного контракта объекта, а не как способ скрыть обычную функцию или простые данные.


Как property использует протокол дескрипторов?

property является дескриптором: при доступе Python вызывает его __get__, при присваивании __set__, при удалении __delete__, если соответствующие функции заданы. Само значение обычно хранят под другим именем, например _price; запись self.price внутри setter снова вызовет setter и приведет к рекурсии. Data descriptor имеет приоритет над одноименным значением в __dict__ экземпляра. Механизм применяют ради ясного контракта объекта, а не как способ скрыть обычную функцию или простые данные.


Как задать абстрактный класс через abc?

Класс наследуют от abc.ABC, а обязательные методы или свойства помечают @abstractmethod. Пока абстрактные члены не реализованы, экземпляр подкласса создать нельзя. ABC может содержать готовые методы и даже реализацию абстрактного метода для кооперативного вызова. Механизм задает номинальный контракт времени выполнения; для структурного статического контракта без наследования подходит typing.Protocol. Механизм применяют ради ясного контракта объекта, а не как способ скрыть обычную функцию или простые данные.


Как согласовать __eq__ и __hash__?

Если a == b, их хеши обязаны совпадать. Поэтому хеш вычисляют только из тех же стабильных полей, что участвуют в равенстве; изменяемый объект с value equality обычно делают нехешируемым. При неизвестном типе __eq__ возвращает NotImplemented, чтобы Python попробовал обратную операцию. Определение __eq__ обычно отключает унаследованный __hash__, если разработчик явно не задал корректный вариант. Механизм применяют ради ясного контракта объекта, а не как способ скрыть обычную функцию или простые данные.


Что означают _ и __ в именах Python?

Один ведущий _name означает внутреннюю деталь по соглашению и влияет на from module import *, но не запрещает доступ. Два ведущих подчеркивания в классе запускают name mangling, например __x превращается в _Class__x, чтобы уменьшить случайные конфликты в наследниках. Имена вида __len__ зарезервированы для специальных протоколов; собственные dunder-имена придумывать не следует. Механизм применяют ради ясного контракта объекта, а не как способ скрыть обычную функцию или простые данные.


Почему альтернативный конструктор возвращает cls(...)?

@classmethod получает фактический класс в cls. Альтернативный конструктор разбирает другую форму входа и возвращает cls(...), поэтому вызов через наследника создает наследника, если его конструктор совместим. Жестко записанное имя базового класса ломает этот полиморфизм. Если фабрика может вернуть разные несвязанные типы или делает сложный I/O, отдельная функция или сервис обычно выражает намерение яснее. Механизм применяют ради ясного контракта объекта, а не как способ скрыть обычную функцию или простые данные.


Что делает декоратор класса?

Декоратор класса вызывается сразу после создания тела класса во время выполнения определения. Он получает класс и возвращает тот же либо другой объект, который связывается с именем. Так регистрируют классы, добавляют методы или превращают их через dataclass. Это отличается от декоратора метода, который оборачивает отдельную функцию до создания класса. Замена класса должна сохранять ожидаемую идентичность и метаданные. Механизм применяют ради ясного контракта объекта, а не как способ скрыть обычную функцию или простые данные.


Как связаны type и object?

Большинство классов являются экземплярами метакласса type, а большинство пользовательских классов наследуют базовый класс object. Поэтому isinstance(C, type) и issubclass(C, object) обычно истинны; сам type тоже наследует object, а object создан метаклассом type. isinstance(x, C) проверяет принадлежность экземпляра, issubclass(A, B) отношение классов. Пользовательские метаклассы должны быть совместимы с метаклассами базовых классов. Механизм применяют ради ясного контракта объекта, а не как способ скрыть обычную функцию или простые данные.

Собеседования: Python

Смотри записи интервью, узнай, какие вопросы задают и как отвечают кандидаты.

Вопросы и ответы

Не нашли ответ? Напишите мне в чат. Я делаю Шпаргалку и сам отвечаю на сообщения. Расскажите, что не работает или чего вам не хватает. Может, смогу сразу взять это в работу.

Откуда взяты вопросы?

Из реальных собеседований. Основой подборки стал опыт Вадима Новосёлова: он проходил интервью и записывал вопросы. Подробнее о материалах.

Насколько эти вопросы актуальны?

Эти вопросы встречались нам на реальных собеседованиях в 2025 году. Мы регулярно проходим собеседования и пополняем подборку новыми вопросами. Основы профессии и ключевые технологии остаются востребованными годами, а детали конкретных инструментов и версий стоит сверять с текущей документацией.

На какой уровень рассчитана подборка?

Мы проходили собеседования на вакансии уровня Middle+, а иногда и на Senior-позиции. Вопросы из этих интервью вошли в подборку. Направления работы: Python-разработчик, Backend-разработчик на Python. Глубина обсуждения зависит от вакансии: будь готов объяснить основную идею, привести практический пример и разобрать ограничения и альтернативы решения.

Этот вопрос точно будет на моём собеседовании?

Гарантии нет: набор вопросов зависит от компании, задач команды, уровня вакансии и самого интервьюера. Эти вопросы уже встречались на реальных собеседованиях, но на твоём интервью ту же тему могут проверить другой формулировкой, практической задачей или обсуждением твоего опыта. Используй подборку, чтобы разобраться в теме: объясняй идею своими словами, приводи примеры и готовься обсудить ограничения и альтернативы решения. Так будет проще ответить и на знакомый вопрос, и на неожиданные уточнения.