对于使用`type()`构造的类型,mypy“作为类型无效”

问题描述 投票:0回答:2

mypy 抱怨

error: Variable "packagename.Foo" is not valid as a type

Foo = type('Foo', (), {})
Bar = Optional[Foo]

可以通过将类型定义为类来修复此错误:

class Foo:
    pass

Bar = Optional[Foo]

还有其他办法解决这个问题吗?我需要保持类型定义动态。

python python-typing mypy
2个回答
9
投票

作为解决方法,这个怎么样?

from typing import Optional, TYPE_CHECKING

if TYPE_CHECKING:
    class Foo: pass
else:
    Foo = type('Foo', (), {})
    
Bar = Optional[Foo]

typing.TYPE_CHECKING
是一个常量,在编译时始终为
True
,在运行时始终为
False
。通过这种方式,我们可以通过仅告诉 MyPy 静态定义来让 MyPy 满意,但在运行时我们可以随心所欲地动态。

不过,您应该意识到,这在很大程度上是一种解决方法,而不是解决方案。通过这样做,我们本质上是在向类型检查器谎报

Foo
的真实定义。这意味着 MyPy 可能无法发现某些地方的错误,并且可能会引发其他地方不存在的错误。在某些情况下,在运行时动态构造类型非常有用,但违背了 Python 中类型检查的一些基本原则,因此如果不进行某种破解,您将很难让类型检查器批准您正在做的事情。


1
投票

这是相关的 mypy issue 8897。就我而言,给出这个例子:

Bla = type("Bla", (), {})  # type: ignore[valid-type, misc]        

class Foo(Bla):
    pass

我可以通过明确输入作业的 LHS 来说服 mypy 接受

Bla

Bla: type = type("Bla", (), {})

仅使用

mypy 1.3.0 (compiled: yes)
进行测试。

© www.soinside.com 2019 - 2024. All rights reserved.