На самом деле вы можете вернуть класс из функции. Ваша синтаксическая ошибка в том, что вы используете ключевое слово класса , как если бы это была функция, которую вы можете вызвать.
Помните, что все блоки классов для - это создание нового класса, а затем привязка к нему выбранного вами имени (в текущей области видимости). Так что просто поместите блок класса в вашу функцию, а затем верните класс!
def mixinFactory(name, base, mixin):
class _tmp(base, mixin):
pass
_tmp.__name__ = name
return _tmp
Как отметил ejucovy , вы также можете позвонить type
напрямую:
def mixinFactory(name, base, mixin):
return type(name, (base, mixin), {})
Это работает, потому что это (обычно) то, что фактически делает блок класса; он собирает все имена, которые вы определяете в блоке класса, в словарь, затем передает имя класса, кортеж базовых классов и словарь в type
для создания нового класса.
Однако type
- это не что иное, как метакласс по умолчанию . Классы являются объектами, как и все остальное, и являются экземплярами класса. Большинство классов являются экземплярами type
, но если задействован другой метакласс, вам следует вызывать его вместо type
, точно так же, как вы не назвали бы object
, чтобы создать новый экземпляр вашего класса.
Ваш миксин (предположительно) не определяет метакласс, поэтому он должен быть совместим с любым метаклассом, который является подклассом type
. Так что вы можете использовать любой класс base
:
def mixinFactory(name, base, mixin):
return base.__class__(name, (base, mixin), {})
Однако комментарий С. Лотта действительно кажется лучшим «ответом» на этот вопрос, если только ваша фабрика микшеров не делает ничего более сложного, чем просто создание нового класса. Это намного понятнее и менее типично, чем любой из предложенных вариантов создания динамического класса:
class NewClass(base, mixin):
pass