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 之禅”的少数方面之一,这个缺陷引发了许多关于 Python 异端和 PSU 成员之间的讨论(例如,请参阅 [EX1][EX2][EX3]),并且还使得大规模企业成功变得不太可能。

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

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

Unicode 使得能够用更少的字符表达更多内容,这与 Python 之禅(“可读性很重要。”)一致。此外,它消除了对单独类型声明语句的需要,最重要的是,它使 Python 能够与 Perl 6 相媲美,Perl 6 已经为其运算符使用了 Unicode。 [2]

规范

当类型声明模式运行时,语法会发生更改,以便每个 NAME 都必须包含两部分:一个名称和一个类型声明符,而类型声明符正好是一个 Unicode 字符。

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

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

仅读取而不赋值的名称后面的类型声明符并非严格必需,但仍会强制执行(请参阅 Python 之禅:“显式优于隐式。”)。

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

类型 声明符
对象 � (替换字符)
int ℕ (双线大写 N)
浮点数 ℮ (估计符号)
布尔值 ✓ (勾号)
复数 ℂ (双线大写 C)
str ✎ (右下铅笔)
Unicode ✒ (黑色笔尖)
元组 ⒯ (带括号的小写字母 t)
列表 ♨ (温泉)
字典 ⧟ (双向多重映射)
集合 ∅ (空集)(注意:这也可以用于满集)
冻结集合 ☃ (雪人)
日期时间 ⌚ (手表)
函数 ƛ (带斜杠的拉丁小写字母 lambda)
生成器 ⚛ (原子符号)
异常 ⌁ (电箭头)

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

这些字符应该对每个程序员来说都很明显、易于记住和输入。

Unicode 替换单元

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

与单个 Unicode 字符相反,他们可以输入 name${UNICODE DECLARATOR OF NAME}$。例如,这两个函数定义是等效的。

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}$

这仍然易于阅读,并且使 ASCII 信徒能够使用类型注解的 Python 的全部功能。

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

最后修改:2025-02-01 08:59:27 GMT