使用具有参数化边界的 TypeVar 的正确方法是什么?



我偶尔会遇到这样的情况:

from typing import Generic, TypeVar
T = TypeVar('T')
class Widget(Generic[T]):
content: T
class Jibbit(Generic[T]):
element: T
class ThingHolder:
thing: Widget | Jibbit

在Python标准库中,这种情况出现在logging.handlers.QueueListener中,其中QueueListener.queue属性相当于上面的ThingHolder.thing

现在我想转换ThingHolder,使其由它所持有的thing的类型参数化,以便我可以区分,例如,ThingHolder[Widget[int]]ThingHolder[Jibbit[int]]

如何用TypeVar正确拼写这个?如果我写

Thing = TypeVar('Thing', bound=Widget | Jibbit)

则会得到一个错误,因为我没有为两个参数化类型指定参数。

似乎应该在bound=本身中参数化类型,而不是尝试参数化新的类型变量:

Thing = TypeVar('Thing', bound=Widget[Any] | Jibbit[Any])

class ThingHolder(Generic[Thing]):
thing: Thing
def __init__(self, thing: Thing) -> None:
self.thing = thing

我最初认为这不会工作,因为"内部"类型参数没有写在定义的任何地方。但它确实有效:

# OK
w_int: Widget[int] = Widget(1)
th_w_int: ThingHolder[Widget[int]] = ThingHolder(w_int)
# OK
w_str: Widget[str] = Widget("hello")
th_w_str: ThingHolder[Widget[str]] = ThingHolder(w_str)
# Errors!
th_w_str = ThingHolder(w_int)
th_w_int = ThingHolder(w_str)
reveal_type(ThingHolder(Jibbit(None)))
# __main__.ThingHolder[__main__.Jibbit[None]]
reveal_type(ThingHolder(Jibbit([1,2,3])))
# __main__.ThingHolder[__main__.Jibbit[builtins.list[builtins.int]]]

认为它有效,因为像Widget[int]这样的东西确实是Widget[Any] | Jibbit[Any]的子类型,而像list[int]这样的东西不是。显然,Mypy足够聪明,可以跟踪"内部"。类型,即使它们没有显式地写在类定义中。而且,如果您有机会在内部参数中注入自己的类型变量,您可能会因为使用错误的内部参数类型方差而意外地把它搞砸。

相关内容

  • 没有找到相关文章

最新更新