PEP 718 – 下标函数

猫勺猫勺 03-18 130 阅读 0 评论

抽象

PEP 建议使函数对象可下标以用于键入目的。这样做 使开发人员能够显式控制类型检查器生成的类型,其中 双向推理(允许匿名的参数类型 功能有待推断)和专业化以外的其他方法是不够的。它 还使函数在能力上与常规类保持一致 可下标。

赋予动机

未知类型

目前,无法将类型参数推断为泛型函数 某些情况:

def make_list[T](*args: T) -> list[T]: ...reveal_type(make_list())  # type checker cannot infer a meaningful type for T

使 subscriptable 的实例允许此构造函数 键入:FunctionType

reveal_type(make_list[int]())  # type is list[int]

目前,您必须使用赋值来提供精确类型:

x: list[int] = make_list()reveal_type(x)  # type is list[int]

但是这段代码不必要地冗长,占用了多个行的简单函数 叫。

同样,在这个例子中,目前无法有意义地推断,所以 无额外分配的非类型化:Tx

def factory[T](func: Callable[[T], Any]) -> Foo[T]: ...reveal_type(factory(lambda x: "Hello World" * x))

但是,如果函数对象是可下标的,则可以给出更具体的类型:

reveal_type(factory[int](lambda x: "Hello World" * x))  # type is Foo[int]

无法判定的推理

甚至在有些情况下,子类关系使类型推断变得不可能。然而 如果可以对函数进行专业化,则类型检查器可以推断出有意义的类型。

def foo[T](x: Sequence[T] | T) -> list[T]: ...reveal_type(foo[bytes](b"hello"))

目前,类型检查器不会始终如一地在此处合成类型。

不可解析类型参数

目前,对于非专用文字,无法确定 类似情况:

def foo[T](x: list[T]) -> T: ...reveal_type(foo([]))  # type checker cannot infer T (yet again)
reveal_type(foo[int]([]))  # type is int

在必须传递特定类型的情况下进行指定也很有用 事先到函数:

words = ["hello", "world"]foo[int](words)  # Invalid: list[str] is incompatible with list[int]

允许订阅使函数和方法与泛型类一致,其中 他们还没有。虽然所有提议的更改都可以使用 可调用的泛型类,语法糖将非常受欢迎。

因此,将功能专业化并将其用作新工厂是可以的

make_int_list = make_list[int]reveal_type(make_int_list())  # type is list[int]

单态化和再化

这个提议也为单态化和具体化类型打开了大门。

这将允许一个轶事已经多次请求的功能。

请注意,此功能不是由 PEP 提出的,但可能会在 未来。

此类功能的语法可能如下所示:

def foo[T]():
   return T.__value__assert foo[int]() is int

理由

此 PEP 中的函数对象用于引用 、 、 和 。FunctionTypeMethodTypeBuiltinFunctionTypeBuiltinMethodTypeMethodWrapperType

因为你应该能够写:MethodType

class Foo:
    def make_list[T](self, *args: T) -> list[T]: ...Foo().make_list[int]()

并让它的工作方式类似于 .FunctionType

对于 ,所以内置泛型函数(例如 和 ) 像 Python 中定义的一样工作。内置函数的行为应与 尽可能用 Python 实现的函数。BuiltinFunctionTypemaxmin

BuiltinMethodType与 是相同的类型。BuiltinFunctionType

MethodWrapperType(例如,类型 ) 可用于 通用的魔术方法。object().__str__

规范

函数对象应实现以允许在运行时进行订阅 并返回一个实例 with set 作为 可调用,并作为类型传递。__getitem__types.GenericAlias__origin____args__

类型检查器应支持下标函数,并了解参数 传递给函数订阅应遵循与泛型可调用对象相同的规则 类。

设置

目前,是设置在 创建被调用类的实例,例如__orig_class__GenericAlias.__call__GenericAlias

class Foo[T]: ...assert Foo[int]().__orig_class__ == Foo[int]

目前,是无条件设置的;但是,为了避免潜在的 擦除任何创建的实例,如果 任何函数对象的实例。__orig_class____origin__

如果没有此更改,以下代码片段将在运行时失败,就像 NOT 一样。__orig_class__bar[str]Foo[int]

def bar[U]():
    return Foo[int]()assert bar[str]().__orig_class__  == Foo[int]

与的互动

重载函数的工作方式应该与现有函数大致相同,因为它们对 运行时类型。唯一的变化是可以决定更多情况,并且 行为/重载可以由开发人员指定,而不是留给排序 的过载/联合。

向后兼容

目前,这些类不可子类化,因此没有向后类 关于已经实现的类的兼容性问题。__getitem__

确认

感谢 Alex Waygood 和 Jelle Zijlstra 对此 PEP 和 Guido 的反馈 举一些激励人心的例子。

版权

本文档置于公有领域或采用 CC0-1.0-Universal 许可协议, 以更宽松的方式为准。

The End 微信扫一扫

文章声明:以上内容(如有图片或视频在内)除非注明,否则均为腾龙猫勺儿原创文章,转载或复制请以超链接形式并注明出处。

本文作者:猫勺本文链接:https://www.jo6.cn/post/69.html

上一篇 下一篇

相关阅读

发表评论

访客 访客
快捷回复: 表情:
评论列表 (暂无评论,130人围观)

还没有评论,来说两句吧...

取消
微信二维码
微信二维码
支付宝二维码