Всё есть объект
Любое значение в 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__() | Список прямых потомков |
Задания
- Выведите
__mro__дляboolи объясните результат. - Создайте класс динамически через
typeс двумя методами. - Реализуйте базовый класс, который с помощью
__init_subclass__собирает всех своих потомков в словарь.
