Статьи

Учебные материалы по языку Python — от основ до продвинутых тем

object и type

Страница 17 из 34 · 2026-10-26 · 3 мин чтения

Всё есть объект

Любое значение в Python — экземпляр некоторого класса, а любой класс — экземпляр метакласса type:

print(type(5))print(type("a"))print(type(len))print(type(int))print(type(type))

Результат: <class 'int'>, <class 'str'>, <class 'builtin_function_or_method'>, <class 'type'>, <class 'type'>.

Класс object

object — вершина иерархии. Все классы прямо или косвенно наследуются от него:

class A:    passprint(A.__mro__)print(issubclass(A, object))print(issubclass(int, object))

Создание «пустого» объекта используется, например, как уникальный маркер:

MISSING = object()def get(d, key, default=MISSING):    if key in d:        return d[key]    if default is MISSING:        raise KeyError(key)    return default

Методы object

МетодНазначение
__init__(self, ...)Инициализация экземпляра
__new__(cls, ...)Создание экземпляра
__del__(self)Вызывается при уничтожении объекта
__repr__(self)Однозначное строковое представление
__str__(self)Читаемое строковое представление
__eq__, __ne__Сравнение на равенство
__lt__, __le__, __gt__, __ge__Сравнение порядка
__hash__(self)Хеш объекта
__bool__(self)Приведение к bool
__getattribute__, __getattr__, __setattr__, __delattr__Доступ к атрибутам
__dir__(self)Список атрибутов для dir
__class__Класс объекта
__dict__Словарь атрибутов экземпляра
__doc__Строка документации
__sizeof__(self)Размер объекта в памяти
__init_subclass__Вызывается при создании подкласса
__format__(self, spec)Форматирование для f-строк и format
__reduce__, __reduce_ex__Поддержка сериализации pickle

Равенство и хеш

Если вы переопределяете __eq__, нужно определить и __hash__, иначе объект станет нехешируемым:

class Point:    def __init__(self, x, y):        self.x = x        self.y = y    def __eq__(self, other):        return isinstance(other, Point) and (self.x, self.y) == (other.x, other.y)    def __hash__(self):        return hash((self.x, self.y))print(len({Point(1, 2), Point(1, 2)}))

Результат: 1.

Функции для работы с типами

ФункцияОписание
type(obj)Точный класс объекта
isinstance(obj, cls)Является ли объект экземпляром класса или его потомка
issubclass(a, b)Является ли класс a потомком b
id(obj)Идентификатор объекта
hash(obj)Хеш объекта
dir(obj)Список имён атрибутов
vars(obj)Словарь __dict__
getattr, setattr, hasattr, delattrДинамический доступ к атрибутам
callable(obj)Можно ли вызвать объект
repr(obj), str(obj)Строковые представления
print(isinstance(True, int))print(type(True) is int)print(isinstance(5, (int, float)))print(hasattr("abc", "upper"))print(getattr("abc", "missing", None))print(callable(len))

Результат: True, False, True, True, None, True.

Предпочитайте isinstance вместо сравнения type(x) == T, так как он учитывает наследование.

Класс type

type — метакласс, создающий классы. Вызов с тремя аргументами создаёт новый класс динамически:

def greet(self):    return f"Привет, {self.name}"Person = type("Person", (), {"name": "Anna", "greet": greet})p = Person()print(p.greet())

Это эквивалентно:

class Person:    name = "Anna"    def greet(self):        return f"Привет, {self.name}"

Собственный метакласс

class Registry(type):    classes = []    def __new__(mcs, name, bases, namespace):        cls = super().__new__(mcs, name, bases, namespace)        mcs.classes.append(cls)        return clsclass Base(metaclass=Registry):    passclass Child(Base):    passprint([c.__name__ for c in Registry.classes])

Результат: ['Base', 'Child']. Для большинства задач проще обойтись декоратором класса или __init_subclass__.

Атрибуты классов

АтрибутОписание
__name__Имя класса
__qualname__Полное имя с учётом вложенности
__module__Имя модуля
__bases__Кортеж прямых родителей
__mro__Порядок разрешения методов
__subclasses__()Список прямых потомков

Задания

  1. Выведите __mro__ для bool и объясните результат.
  2. Создайте класс динамически через type с двумя методами.
  3. Реализуйте базовый класс, который с помощью __init_subclass__ собирает всех своих потомков в словарь.