ООП. Классы и методы
Какие типы классов существуют в 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, следует:-
Определить класс с помощью ключевого слова
class. -
Использовать неизменяемые значения полей. Двойное подчёркивание меняет имя атрибута, но не запрещает его изменение.
-
Создать методы только для чтения атрибутов класса (без методов для изменения значений).
-
Переопределить методы
__setattr__()и__delattr__(), чтобы они возбуждали исключениеAttributeError, предотвращая изменение атрибутов класса. -
По желанию, переопределить метод
__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 могут быть созданы и использованы так же, как и любые другие объекты данных.
Ссылки для изучения
Примеры хороших ответов из реальных собеседований
- Тестовое интервью Junior Python-разработчика · 10:01–10:38Мок-собеседование · Ответ кандидата
Кандидат подтверждает, что функция в Python является объектом, который хранит исполняемый код и может быть вызван для работы с другими объектами.
Какой класс может создавать другие классы в Python?
В Python класс, который создает другие классы, называется метаклассом. Метаклассы представляют собой специальные классы, экземпляры которых сами являются классами. Они управляют созданием, поведением и структурой других классов. Метаклассы обычно используются для изменения поведения классов, добавления магических методов или управления созданием экземпляров классов.
Ссылки для изучения
Примеры хороших ответов из реальных собеседований
- Мок-собеседование Senior Python-разработчика · 21:31–22:06Мок-собеседование · Ответ кандидата
Кандидат объясняет, что класс сам является экземпляром метакласса type, от которого наследуются пользовательские метаклассы.
Какой самый первый метакласс в 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__; наследование требует аккуратно объявлять слоты на каждом уровне. Это оптимизация представления экземпляров, а не механизм приватности, и выгоду следует измерять на реальной модели. Механизм применяют ради ясного контракта объекта, а не как способ скрыть обычную функцию или простые данные.
Ссылки для изучения
Примеры хороших ответов из реальных собеседований
- Мок-интервью Python-разработчика: типизация, память и asyncio · 23:00–23:28Мок-собеседование · Ответ кандидата
Кандидат объясняет, что __slots__ ограничивает набор атрибутов, убирает обычный __dict__ и экономит память при большом числе экземпляров.
Чем __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) отношение классов. Пользовательские метаклассы должны быть совместимы с метаклассами базовых классов. Механизм применяют ради ясного контракта объекта, а не как способ скрыть обычную функцию или простые данные.
Ссылки для изучения







