Following system colour scheme - Python 增强提案 Selected dark colour scheme - Python 增强提案 Selected light colour scheme - Python 增强提案

Python 增强提案

PEP 3117 – 后缀类型声明

作者:
Georg Brandl <georg at python.org>
状态:
已拒绝
类型:
标准跟踪
创建:
2007 年 4 月 1 日
Python 版本:
3.0
历史记录:


目录

摘要

本 PEP 提出在 Python 中添加后缀类型声明语法。它还指定了一个新的 typedef 语句,用于在类型和声明符之间创建新的映射。

它的接受将极大地增强 Python 用户体验,并消除阻止其他编程语言用户转向 Python 的一个缺点。

基本原理

长期以来,Python 一直缺乏显式类型声明。作为该语言偏离其禅宗的少数几个方面之一,这个缺点引发了 Python 异端分子和 PSU 成员之间的许多讨论(例如,参见 [EX1][EX2][EX3]),它也使它不太可能成为大规模的企业成功。

但是,如果想结束这种痛苦,就必须找到一种合适的 Python 语法。在几乎所有拥有类型声明的语言中,类型声明都缺乏这种品质:它们冗长,通常需要多个单词来表示一个类型,或者难以理解(例如,某种语言使用完全无关的 [1] 形容词,如 dim 来进行类型声明)。

因此,本 PEP 将转向类型声明与另一个大胆的举动结合起来,这将再次证明 Python 不仅是面向未来的,而且是拥抱未来的:引入 Unicode 字符作为源代码的组成部分。

Unicode 使得用更少的字符表达更多内容成为可能,这符合 禅宗(“可读性很重要。”)。此外,它消除了对单独的类型声明语句的需求,最后但并非最不重要的是,它使 Python 赶上了 Perl 6,Perl 6 已经使用 Unicode 来表示其运算符。 [2]

规范

当类型声明模式处于活动状态时,语法将发生更改,因此每个 NAME 必须包含两个部分:一个名称和一个类型声明符,它恰好是一个 Unicode 字符。

声明符唯一地指定名称的类型,如果它出现在表达式的左侧,则将强制执行此类型:如果返回的类型与声明的类型不匹配,则会引发 InquisitionError 异常。 [3]

此外,必须指定函数调用结果类型。如果调用的结果不具有声明的类型,则会引发 InquisitionError。注意:结果的声明符不应与函数对象的声明符混淆(参见下面的示例)。

仅读取而不赋值的名称后面的类型声明符不是严格必需的,但无论如何都会被强制执行(参见 Python 禅宗:“显式优于隐式。”)。

类型与声明符之间的映射不是静态的。它可以由程序员完全自定义,但为了方便起见,某些内置类型有一些预定义的映射

类型 声明符
object � (替换字符)
int ℕ (双线大写 N)
float ℮ (估计符号)
bool ✓ (复选标记)
complex ℂ (双线大写 C)
str ✎ (右下角铅笔)
unicode ✒ (黑色笔尖)
tuple ⒯ (带括号的小写拉丁字母 T)
list ♨ (温泉)
dict ⧟ (双端多映射)
set ∅ (空集) (注意:这也适用于完整集)
frozenset ☃ (雪人)
datetime ⌚ (手表)
function ƛ (带撇号的小写拉丁字母 lambda)
generator ⚛ (原子符号)
Exception ⌁ (电箭头)

None 类型的声明符是零宽度空格。

这些字符对每个程序员来说都应该是显而易见、易于记忆和输入的。

Unicode 替换单元

由于即使在我们现代的全球化世界中,仍然有一些老派的叛逆者无法或不想在他们的源代码中使用 Unicode,并且由于 Python 是一种宽容的语言,因此为这些人提供了一种备用方案

他们可以使用 name${UNICODE NAME OF THE DECLARATOR}$ 而不是单个 Unicode 字符。例如,这两个函数定义是等效的

def fooƛ(xℂ):
    return None

以及

def foo${LATIN SMALL LETTER LAMBDA WITH STROKE}$(x${DOUBLE-STRUCK CAPITAL C}$):
    return None${ZERO WIDTH NO-BREAK SPACE}$

这仍然易于阅读,并将类型注释 Python 的全部功能提供给 ASCII 信徒。

The typedef 语句

可以使用此新语句扩展类型与声明符之间的映射。

语法如下

typedef_stmt  ::=  "typedef" expr DECLARATOR

其中 expr 解析为一个类型对象。为了方便起见,typedef 语句也可以与 class 语句混合使用,用于新类,如下所示

typedef class Foo☺(object�):
    pass

示例

这是标准的 os.path.normpath 函数,已转换为类型声明语法

def normpathƛ(path✎)✎:
    """Normalize path, eliminating double slashes, etc."""
    if path✎ == '':
        return '.'
    initial_slashes✓ = path✎.startswithƛ('/')✓
    # POSIX allows one or two initial slashes, but treats three or more
    # as single slash.
    if (initial_slashes✓ and
        path✎.startswithƛ('//')✓ and not path✎.startswithƛ('///')✓)✓:
        initial_slashesℕ = 2
    comps♨ = path✎.splitƛ('/')♨
    new_comps♨ = []♨
    for comp✎ in comps♨:
        if comp✎ in ('', '.')⒯:
            continue
        if (comp✎ != '..' or (not initial_slashesℕ and not new_comps♨)✓ or
             (new_comps♨ and new_comps♨[-1]✎ == '..')✓)✓:
            new_comps♨.appendƛ(comp✎)
        elif new_comps♨:
            new_comps♨.popƛ()✎
    comps♨ = new_comps♨
    path✎ = '/'.join(comps♨)✎
    if initial_slashesℕ:
        path✎ = '/'*initial_slashesℕ + path✎
    return path✎ or '.'

如您所见,类型声明增加了表达能力,同时使代码看起来更加专业。

兼容性问题

要启用类型声明模式,必须编写

from __future__ import type_declarations

这将启用源代码的 Unicode 解析 [4],使 typedef 成为关键字,并强制对所有赋值和函数调用进行正确的类型检查。

拒绝

经过仔细考虑、认真反省、咬牙切齿和撕心裂肺之后,我们决定拒绝本 PEP。

参考资料

致谢

衷心感谢 Armin Ronacher、Alexander Schremmer 和 Marek Kubica,他们帮助找到了最合适和最具助记的内置类型声明符。

还要感谢 Unicode 联盟将所有这些有用的字符包含在 Unicode 标准中。


来源:https://github.com/python/peps/blob/main/peps/pep-3117.rst

上次修改时间:2023 年 9 月 9 日 17:39:29 GMT