Динамически создавать класс, производный от класса ABC

Я использую пользовательский кодировщик PyMongo bson. Поскольку кодировщик не может быть унаследован, его нужно создавать для каждого класса, поэтому я хочу создать для него кодировщик динамически.

Проблема в том, что базовый кодировщик (TypeEncoder) создается из класса ABC. Когда я пытался создать класс, используя этот код:

from bson.codec_options import TypeEncoder

cls_encoder = type(f"Flag{cls.__name__}Encoder", 
                   (TypeEncoder,),
                   {"transform_python": lambda self, value: value.code,
                    "python_type": property(lambda self: cls)})

Результат будет

>> isinstance(cls_encoder, TypeEncoder)
False
>> type(cls_encoder)
<class 'abc.FlagAutoReplyContentTypeEncoder'>
>> super(cls_encoder)
<super: <class 'FlagAutoReplyContentTypeEncoder'>, NULL>

Ожидаемый результат должен быть

>> isinstance(cls_encoder, TypeEncoder)
True

Примечание: переменная cls будет Enum Примечание: python_type — это abstractproperty; transform_python — это функция, которая принимает значение типа python_type и возвращает что-то вроде тип допустим для сериализации bson.


Я пробовал это:

class FlagBsonEncoder(TypeEncoder):
    def transform_python(self, value):
        return value.code

cls_encoder = type(f"Flag{cls.__name__}Encoder", 
                   (FlagBsonEncoder,),
                   {"python_type": property(lambda self: cls)})

Но все тот же результат:

>> isinstance(cls_encoder, TypeEncoder)
False

Вот официальный пример того, как использовать кодировку пользовательского типа: http://api.mongodb.com/python/current/api/bson/codec_options.htmlhttp://api.mongodb.com/python/current/examples/custom_type.html#custom-type-type-codec

Почему в Python есть оператор "pass"?
Почему в Python есть оператор "pass"?
Оператор pass в Python - это простая концепция, которую могут быстро освоить даже новички без опыта программирования.
Некоторые методы, о которых вы не знали, что они существуют в Python
Некоторые методы, о которых вы не знали, что они существуют в Python
Python - самый известный и самый простой в изучении язык в наши дни. Имея широкий спектр применения в области машинного обучения, Data Science,...
Основы Python Часть I
Основы Python Часть I
Вы когда-нибудь задумывались, почему в программах на Python вы видите приведенный ниже код?
LeetCode - 1579. Удаление максимального числа ребер для сохранения полной проходимости графа
LeetCode - 1579. Удаление максимального числа ребер для сохранения полной проходимости графа
Алиса и Боб имеют неориентированный граф из n узлов и трех типов ребер:
Оптимизация кода с помощью тернарного оператора Python
Оптимизация кода с помощью тернарного оператора Python
И последнее, что мы хотели бы показать вам, прежде чем двигаться дальше, это
Советы по эффективной веб-разработке с помощью Python
Советы по эффективной веб-разработке с помощью Python
Как веб-разработчик, Python может стать мощным инструментом для создания эффективных и масштабируемых веб-приложений.
2
0
88
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Я думаю, вы неправильно понимаете, что делает isinstance.

isinstance(cls_encoder, TypeEncoder) спрашивает, является ли объект классаcls_encoder экземпляром TypeEncoder. Конечно нет - это тип!

Что вам нужно, так это isinstance(cls_encoder(), TypeEncoder), который спрашивает, является ли экземпляр cls_encoder также экземпляром TypeEncoder, что, конечно же, должно быть правдой.

Если вы хотите проверить, является ли класс cls_encoderподкласс класса TypeEncoder, вы можете использовать issubclass(cls_encoder, TypeEncoder).

Ты прав, лол, я забыл создать экземпляр, чтобы проверить это. Спасибо за помощь! :D

RaenonX 29.05.2019 11:38

Если вы считаете, что ответ @gmds помог вам, вы можете рассмотреть что делать, когда кто-то отвечает на мой вопрос и как принять мой ответ

Reblochon Masque 29.05.2019 11:43

@ReblochonMasque спасибо за советы. Я принял этот ответ, но не могу проголосовать из-за отсутствия репутации.

RaenonX 29.05.2019 12:02

Хорошо тебе, спасибо! Теперь вашего представителя должно быть достаточно, чтобы проголосовать.

Reblochon Masque 29.05.2019 12:03

Все еще нужно 2, хахаха, постараюсь не забыть проголосовать, когда получу 15, и вернуться сюда.

RaenonX 14.06.2019 02:40

Другие вопросы по теме