Содржина на објавата
Как создать новый тип объекта? Очень просто! Cоздайте новый класс. class MyType: pass Такой способ подходит для создания класса, статично записанного в скрипт. Но бывают случаи когда мы заранее не знаем какие атрибуты и методы будут у класса. То есть требуется динамическое создание класса во время исполнения кода. Для чего? Самое очевидное использование это Mock-объекты. Когда нам нужно подменить оригинальный объект заглушкой. Регулярно используется в авто тестах и в генераторах документации. Есть даже специальный класс для этого unittest.mock.Mock. Можем на лету создавать класс и настраивать его поведение. >>> from unittest.mock import Mock >>> dyn_obj = Mock() >>> dyn_obj.return_value = 123 >>> print(dyn_obj()) 123 Также можно создать инлайн тип с помощью функции type(). MyType = type("MyType", (object,), {"func": lambda: 123, "attr": 321}) Первый аргумент это имя нового объекта. Второй аргумент это список родительских классов. Третий, это неймспейс объекта, то есть его методы и атрибуты. В неймспейсе можно указывать как просто данные так и функции. Однажды, для совместимости со старым кодом потребовалось немного изменить имеющийся класс. Был переименован метод и нужно было временно сделать заглушку. Писать отдельный класс не хотелось, а нужен был именно класс а не инстанс, к тому же не надолго. Вот тут и пригодился данный трик. # старый класс class OldClass: def old_method(self): return 123 # вариант с переопределением старого класса class OldClass(OldClass): def new_method(self): return self.old_method() # тоже самое но с динамически созданным типом непосредственно в том месте где он требуется OldClass = type('NewClass', (OldClass,), {'new_method': lambda self: self.old_method()}) >>> obj = OldClass() >>> print (obj.new_method(), obj.old_method()) (123, 123) Пример из практики #1 Был случай, когда я написал собственную реализацию запросов на сервер. Некий аналог requests, но очень простой, на чистых сокетах. Это требовалось потому, что в исполняемой среде была версия Python, в которой никак не хотел работать оригинальный requests, да и слишком тяжёлый он был. При этом интерфейс ответа требовалось сохранить как в requests, но не всегда а по запросу, то есть динамически. Пример из практики #2 Для некоторых, не совсем логичных, но всё же целей, требовалось воссоздавать типы, которые прилетели в виде JSON-данных. Структура типа и данные инстанса были в этом JSON. Оставалось только пересобрать класс и создать инстанс. Некое подобие pickle, только немного иначе. Но это уже достаточно сложные примеры для поста. Пожалуй, код опустим)))😊 #tricks