您的类型签名非常好,您的 IDE 应该报告这一点instance
and instance2
属于类型Test1
and Test2
分别。事实上,如果您尝试运行代码,您将得到的输出mypy http://mypy-lang.org/。 (要揭示 mypy 认为您的类型是什么,请尝试暂时添加reveal_locals()
在运行 mypy 之前将伪函数添加到代码底部。)
然而,实际情况body您的代码实际上在技术上也不健全!代码的调用者可以传入一个自定义对象,该对象决定始终认为自己等于一切。例如:
from typing import TypeVar, Type
class ForceAlwaysEqual(type):
def __new__(cls, name, bases, dct):
return super().__new__(cls, name, bases, dct)
def __eq__(self, other) -> bool:
return True
class Hijacked(metaclass=ForceAlwaysEqual): pass
class Test1: pass
class Test2: pass
T = TypeVar('T')
def create(t: Type[T]) -> T:
if t == Test1:
return Test1()
elif t == Test2:
return Test2()
else:
raise ValueError()
mystery = create(Hijacked)
print(type(mystery))
如果您尝试在 Python 中运行此代码,我们将打印出Test1
最后:调用create
不会抛出 ValueError!
这里基本上发生的是我添加了一个自定义元类Hijacked
所以这样做Hijacked == blah
将始终返回 True。这会导致 create (t == Test1
) 恰好为 true,因此我们返回 Test1,这违反了函数的签名。
因此,如果您的 IDE 也没有指示任何问题body你的create
函数,这实际上在技术上是他们的另一个错误。
(这里更普遍的教训是,在 Python 中,不幸的是,类型检查器很难从相等性检查中推断出大部分内容,因为它们可以随时被重新定义以执行任何数量的任意废话。)