【问题标题】:Mypy rejects type objects created with `type(name, (bases,), {})`Mypy 拒绝使用 `type(name, (bases,), {})` 创建的类型对象
【发布时间】:2017-12-04 13:31:45
【问题描述】:

我在让 mypy 接受类型对象时遇到了一些麻烦。我是 确信我只是做错了,但到目前为止我的谷歌搜索并没有让我得到任何答案。

class Good(object):
    a = 1

def works(thing: Good):
    print(thing.a)

o = Good()
works(o)

Bad = type('Bad', (object, ), dict(a=1))

def fails_mypy(thing: Bad):
    print(thing.a)

s = Bad()
fails_mypy(s)

像'Good'这样构造的东西是可以的,而像'Bad'这样构造的东西却通过以下方式使mypy检查失败:

error: Invalid type "test.Bad"
error: Bad? has no attribute "a"

【问题讨论】:

    标签: python python-3.x types python-3.6 mypy


    【解决方案1】:

    基于mypys wiki 的Unsupported Python Features 部分,目前不支持此类类的运行时创建。它无法理解您的函数定义中的 Bad 是什么。在执行mypy 时使用reveal_type(Good)reveal_type(Bad) 应该清楚这一点。

    一种使这些静音的方法是使用Any。要么使用 Python 3.6 变量注释语法:

    Bad: Any = type('Bad', (), {'a':1})
    

    或者,使用 Python

    Bad = type('Bad', (), {'a':1}) # type: Any
    

    (在这两种情况下,Any 都应首先从 typing 导入)

    当然,这基本上意味着您的函数现在可以接受任何内容。需要付出代价,但这就是动态语言所得到的;因为Bar 是在运行时定义的,它可以理论上是任何东西:-)

    【讨论】:

    • 如果您动态创建的类有某种通用接口,您可以创建一个抽象基类来封装它并将其用作基础之一。然后,您可以使用Type[MyBaseClass],而不是使用Any。 (如果有其他一些共同点,同样适用。)这并没有太大的改进,但比Any略好。
    猜你喜欢
    • 1970-01-01
    • 2020-02-23
    • 2019-12-22
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-08-25
    • 2012-12-28
    • 1970-01-01
    相关资源
    最近更新 更多