人们经常说 RPython(Python 的子集)是静态类型的。 (例如在维基百科上。)
最初,我想知道他们如何将其添加到 Python 中,并认为他们可能添加了在每个函数的开头添加诸如
assert isinstance(arg1, ...)
之类的语句的要求(但我真的不敢相信)。
然后我查看了一些 RPython 代码,它看起来根本不是静态类型的。在许多情况下,编译器可能可以证明函数参数只能是某些类型,但绝对不是在所有情况下都是如此。
例如,这是
string.split
的 RPython 实现:
def split(value, by, maxsplit=-1):
bylen = len(by)
if bylen == 0:
raise ValueError("empty separator")
res = []
start = 0
while maxsplit != 0:
next = value.find(by, start)
if next < 0:
break
res.append(value[start:next])
start = next + bylen
maxsplit -= 1 # NB. if it's already < 0, it stays < 0
res.append(value[start:len(value)])
return res
在有关 RPython 的 PyPy 文档中,据说:“变量应该包含至多一种类型的值”。
那么,函数参数也算作变量吗?或者说 RPython 在什么意义上是静态类型的?还是说这实际上是错误的?
那么,函数参数也算作变量吗?
当然有。他们总是用几乎所有语言。
或者 RPython 在什么意义上是静态类型的?还是说这实际上是错误的?
该说法正确。 RPython 不是 Python。 嗯,它是 Python 的子集,可以作为 Python 代码运行。但是当你实际编译 RPython 代码时,你会失去太多的动态性(尽管只有在导入时间之后,所以你仍然可以使用元类,从字符串生成代码等 - 在某些模块中效果很好),编译器(这不是 Python 编译器,但与传统编译器有很大不同;请参阅相关文档)确实可以决定静态使用类型。更准确地说,使用动态性的代码使其通过了解析器和所有内容,但在某些时候会导致类型错误。
在许多情况下,编译器可能可以证明函数参数只能是某些类型,但绝对不能在所有情况下都如此。当然不是。有很多代码不是静态类型的,并且相当多的静态类型代码当前注释器无法证明是静态类型的。但是当遇到这样的代码时,这是一个编译错误,句号。
有几点需要注意:
(嗯,在大多数情况下;我相信有一些函数需要断言来帮助注释者)。静态类型并不(正如您在评论中暗示的那样)意味着必须写出类型(这称为清单类型),它意味着每个表达式(包括变量)都有一个永远不会改变的类型。
def add(a, b): return a + b
(参数可能是整数、浮点数、字符串、列表等),但如果使用整数参数调用函数(例如整数文字或变量)之前被推断为包含整数),则确定
a
和b
(并且根据+
的类型,add
的结果)也是整数。
rlib.parsing
中)在编译时运行并生成 RPython 代码,但不是 RPython(顺便说一下,通常带有
"NOT_RPYTHON"
文档字符串)。此外,标准库的大部分都是用完整的 Python 编写的(大部分直接取自 CPython)。
描述了一般的转换过程,包括类型推断,而RPython Typer描述了所使用的类型系统。