В одном приложении у меня есть код, который генерирует динамические классы, что значительно уменьшает количество дублированного кода. Но добавление подсказок типа для проверки mypy привело к ошибке. Рассмотрим следующий пример кода (упрощенный, чтобы сосредоточиться на соответствующих битах):
class Mapper:
@staticmethod
def action() -> None:
raise NotImplementedError('Not yet implemnented')
def magic(new_name: str) -> type:
cls = type('%sMapper' % new_name.capitalize(), (Mapper,), {})
def action() -> None:
print('Hello')
cls.action = staticmethod(action)
return cls
MyCls = magic('My')
MyCls.action()
Проверка этого с помощью mypy приведет к следующей ошибке:
dynamic_type.py:15: error: "type" has no attribute "action"
dynamic_type.py:21: error: "type" has no attribute "action"
mypy, очевидно, не может определить, что возвращаемое значение из вызова type
является подклассом Mapper
, поэтому он жалуется, что "тип" не имеет атрибута "действие", когда я ему присваиваю.
Обратите внимание, что код работает отлично и делает то, что должен, но mypy по-прежнему жалуется.
Есть ли способ пометить cls
как тип Mapper
? Я попытался просто добавить # type: Mapper
в строку, создающую класс:
cls = type('%sMapper' % new_name.capitalize(), (Mapper,), {}) # type: Mapper
Но тогда я получаю следующие ошибки:
dynamic_type.py:10: error: Incompatible types in assignment (expression has type "type", variable has type "Mapper")
dynamic_type.py:15: error: Cannot assign to a method
dynamic_type.py:15: error: Incompatible types in assignment (expression has type "staticmethod", variable has type "Callable[[], None]")
dynamic_type.py:16: error: Incompatible return value type (got "Mapper", expected "type")
dynamic_type.py:21: error: "type" has no attribute "action"