为什么Python不允许单一类型约束?

76
假设你想限制一个类型变量实现某个接口。你可以这样写:
from typing import TypeVar, Callable

T = TypeVar('T', Callable)

class Foo(Generic[T]):
    ...

>> TypeError: A single constraint is not allowed

为什么Python对类型约束的使用不满意?PEP 484Python源代码在这方面没有帮助。

注意:在我的特定情况下,我想限制一个类型变量实现一个抽象基类,但原则是相同的。

1个回答

91
你正在寻找“bound”:

你正在寻找bound

T = TypeVar('T', bound=Callable)

来自文档:

类型变量可以使用bound=<type>指定上限。这意味着替换(明确或隐含地)类型变量的实际类型必须是边界类型的子类,参见PEP 484。

TypeVar(name, *args)表示类型必须是args之一,因此如果允许T = TypeVar('T', Callable),则所有T的实例都可以被Callable替换。

你应该能看到这里的不同之处(尽管我并没有真的尝试过,嘿):

from typing import Generic, TypeVar, Callable

T = TypeVar('T', Callable, bool)

class Foo(Generic[T]):
    value: T

    def __init__(self, value: T) -> None:
        self.value = value

class Bar:
    baz = 5

    def __call__(self):
        pass

f = Foo(Bar())
print(f.value.baz)  # doesn’t typecheck because f.value is only a Callable

小的后续问题:您有没有想过如何访问绑定到类型变量的类型的构造函数?具体来说,我想在泛型类的__init__中调用T() - alcorn
1
@alcorn:那不是一个打字级别的操作,所以我相信这是不可能/不应该被完成的。你可以让使用者通过 Type[T] 类型的参数传递类。 - Ry-
1
好的,我明白了。我陷入了这样一种思维误区,认为Python的类型参数与C++/Java/C#等语言中的同一特性是可比较的,但实际上它们(目前)只有在运行时强制执行类型约束方面��有用:它们不能代替实际值。 - alcorn
1
@alcorn 快速搜索得到 https://dev59.com/GsPra4cB1Zd3GeqPlKrk,https://stackoverflow.com/q/67757839/688080 和 https://dev59.com/CWkMtIcB2Jgan1znVVo3。 - Ziyuan

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接