Python 打字:如何让 Type[C] 与 TypeVars 和泛型一起工作?
Posted
技术标签:
【中文标题】Python 打字:如何让 Type[C] 与 TypeVars 和泛型一起工作?【英文标题】:Python Typing: how to get Type[C] to work with TypeVars and Generics? 【发布时间】:2019-02-26 04:04:55 【问题描述】:我试图弄清楚如何让 Python 泛型类型提示与 Type[C] 的构造函数参数配合得很好。考虑这个代码示例:
class Foo(object):
fooval: str
def __init__(self, val):
self.fooval = val
class Bar(object):
barval: str
def __init__(self, val):
self.barval = val
T = TypeVar('T', Foo, Bar)
class FooBarContainer(Generic[T]):
child: T
# Type[T] seems logical here, but that's not valid according to the docs
def __init__(self, ctorable: Type[Union[Foo, Bar]], val):
self.child = ctorable(val)
baz = FooBarContainer(Foo, val)
# This does not get flagged by type-checkers, but will obviously fail at runtime
failure = baz.child.barval
尝试使用 Type[T] 会导致类型检查器错误:
预期类型[T],得到类型[Foo]
所以这里的目标是弄清楚如何让 TypeVars 与 Type[C] 一起工作。这样静态分析就会知道,当我用特定的 Type[T] 调用特定的 func 时,我期望得到 T。我似乎在这里找不到任何可以帮助我的文档。
在处理函数时也会出现同样的问题。例如,这是有效的语法,但在输入方面显然无效:
def initor(thing_type: Type[Union[Foo, Bar]], val) -> T:
return thing_type(val)
【问题讨论】:
【参考方案1】:您能否澄清“Type[T] 在这里似乎合乎逻辑,但根据文档无效”是什么意思?
具体来说,您正在查看哪些文档?以下代码使用 mypy 0.630 按预期工作:
class FooBarContainer(Generic[T]):
child: T
def __init__(self, ctorable: Type[T], val) -> None:
self.child = ctorable(val)
val = 3
baz = FooBarContainer(Foo, val)
# Mypy reports a `"Foo" has no attribute "barval"` error
failure = baz.child.barval
如果文档暗示给ctorable
提供Type[T]
类型不起作用,则可能应该更新它们。
【讨论】:
感谢您的回复!我正在使用 PyCharm 的类型检查来分析这个,所以现在我想知道这是否是我的问题!我将不得不针对我的代码测试 mypy 并看看它是如何做的。这给了我一个很好的线索。我正在查看的文档在这里:docs.python.org/3/library/typing.html#typing.Type 我可能误读了这一行:Type 的唯一合法参数是类、类的联合和 Any。我不确定 TypeVar 在这里是否是一个有效值,而且 PyCharm 似乎无法理解 Type[T] 的事实给了我一个潜在的错误偏见。 @Zoinks -- 哦,这太尴尬了……我实际上是贡献文档特定部分的人 -- 我不确定我为什么要写这个。Type[T]
可能在 2 年前确实没有被考虑(当时我写了文档的那部分);我也有可能完全忘记了类型变量。有点恼人的是,PEP 484 给出了完全不同的答案:似乎认为Type[T]
是合法的,但仅在注释类方法的第一个参数时...
无论如何,一旦我得到澄清,我会四处询问+发布更新评论。
哦,非常整洁!感谢您抽出宝贵的时间,谢谢。
@Zoinks -- 打字文档是updated now; PEP 484 可能需要更长的时间来更新,主要是因为必要的措辞更改需要更多的工作。以上是关于Python 打字:如何让 Type[C] 与 TypeVars 和泛型一起工作?的主要内容,如果未能解决你的问题,请参考以下文章
如何让 Python 数据类 InitVar 字段与 typing.get_type_hints 一起使用,同时还使用注释?
打字稿:键入'字符串| undefined' 不能分配给 type 'string'