繁体   English   中英

如何为动态创建的类添加类型注释?

[英]How can I add type-annotations to dynamically created classes?

在一个应用程序中,我有生成动态类的代码,该类大大减少了重复代码的数量。 但是,添加用于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 # 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"

一种可能的解决方案基本上是:

  1. 使用预期的输入和输出类型键入您的magic函数
  2. 明智地使用Any# type: ignore ,使magic函数的内容保持动态# type: ignore

例如,类似这样的方法将起作用:

class Mapper:
    @staticmethod
    def action() -> None:
        raise NotImplementedError('Not yet implemnented')


def magic(new_name: str) -> Mapper:

    cls = type('%sMapper' % new_name.capitalize(), (Mapper,), {})

    def action() -> None:
        print('Hello')

    cls.action = staticmethod(action)  # type: ignore
    return cls  # type: ignore


MyCls = magic('My')
MyCls.action()

保留部分代码动态键入似乎有些令人反感,但在这种情况下,我认为没有任何避免的方法:mypy(和PEP 484输入生态系统)故意不尝试处理超动态代码,例如这个。

相反,您能做的最好的事情就是干净地记录“静态”界面,添加单元测试,并将代码的动态部分限制在尽可能小的区域内。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM