对象空间¶
简介¶
对象空间创建 PyPy 中的所有对象,并知道如何在它们上执行操作。将对象空间视为提供固定 API 的库可能会有所帮助:一组操作,以及与 Python 对象的已知语义相对应的实现。
例如,add()
是一个操作,在对象空间中具有执行数值加法(当 add()
对数字进行操作时)、串联(当 add()
对序列进行操作时)等的实现。
我们有一些可以插入字节码解释器的工作对象空间
- 标准对象空间 是 Python 中各种内置类型和对象的完整实现。标准对象空间与字节码解释器一起构成了我们 Python 实现的基础。在内部,它是一组 解释器级 类,实现了各种 应用程序级 对象——整数、字符串、列表、类型等。为了与 CPython 进行比较,标准对象空间提供了与 C 结构
PyIntObject
、PyListObject
等的等效项。 - 各种 对象空间代理 包装另一个对象空间(例如标准对象空间),并添加新功能,例如延迟计算对象(仅在对它们执行操作时计算)、安全检查对象、分布在多台机器上的对象等。
此处记录的各种对象空间可以在 pypy/objspace 中找到。
请注意,大多数对象空间操作接受并返回 应用程序级 对象,这些对象被解释器视为不透明的“黑盒”。只有极少数操作允许字节码解释器了解应用程序级对象的某些值。
对象空间接口¶
这是所有对象空间实现的公共 API
管理功能¶
-
getexecutioncontext
()¶ 返回当前活动的执行上下文。(pypy/interpreter/executioncontext.py).
-
getbuiltinmodule
(name)¶ 返回由
name
指定的内置模块的Module
对象。 (pypy/interpreter/module.py).
对象空间中的操作¶
这些函数都接受和返回“包装”的(即 应用程序级)对象。
以下函数实现了具有直接对应于语言级构造的简单语义的操作
id, type, issubtype, iter, next, repr, str, len, hash,
getattr, setattr, delattr, getitem, setitem, delitem,
pos, neg, abs, invert, add, sub, mul, truediv, floordiv, div, mod, divmod, pow, lshift, rshift, and_, or_, xor,
nonzero, hex, oct, int, float, long, ord,
lt, le, eq, ne, gt, ge, cmp, coerce, contains,
inplace_add, inplace_sub, inplace_mul, inplace_truediv, inplace_floordiv, inplace_div, inplace_mod, inplace_pow, inplace_lshift, inplace_rshift, inplace_and, inplace_or, inplace_xor,
get, set, delete, userdel
-
call
(w_callable, w_args, w_kwds)¶ 使用给定的位置 (
w_args
) 和关键字 (w_kwds
) 参数调用函数。
-
index
(w_obj)¶ 使用
w_obj
实现索引查找 (如 CPython 2.5 中引入的那样)。将返回一个包装的整数或长整数,或者如果对象没有__index__()
特殊方法,则引发TypeError
。
-
is_
(w_x, w_y)¶ 实现
w_x is w_y
。
-
isinstance
(w_obj, w_type)¶ 使用
type(w_obj)
和w_type
作为参数实现issubtype()
。
便利函数¶
以下函数使用频率很高,因此将它们作为快捷方式引入是值得的——但是,它们并非严格必要,因为它们可以使用其他几个对象空间方法来表达。
-
eq_w
(w_obj1, w_obj2)¶ 当
w_obj1
和w_obj2
相等时返回True
。是space.is_true(space.eq(w_obj1, w_obj2))
的快捷方式。
-
is_w
(w_obj1, w_obj2)¶ 是
space.is_true(space.is_(w_obj1, w_obj2))
的快捷方式。
-
hash_w
(w_obj)¶ 用于
space.int_w(space.hash(w_obj))
的快捷方式。
-
len_w
(w_obj)¶ 用于
space.int_w(space.len(w_obj))
的快捷方式。
注意 以上四个函数返回的是 解释器级别 对象,而不是 应用程序级别 对象!
-
not_
(w_obj)¶ 用于
space.newbool(not space.is_true(w_obj))
的快捷方式。
-
finditem
(w_obj, w_key)¶ 等效于
getitem(w_obj, w_key)
,但如果未找到键,则返回一个 **解释器级别** 的 None,而不是引发 KeyError。
-
call_function
(w_callable, *args_w, **kw_w)¶ 将参数收集到一个包装的元组和字典中,并调用
space.call(w_callable, ...)
。
-
call_method
(w_object, 'method', ...)¶ 使用
space.getattr()
获取方法对象,然后使用space.call_function()
调用它。
-
unpackiterable
(w_iterable[, expected_length=-1])¶ 遍历
w_x
(使用space.iter()
和space.next()
),并将生成的包装对象收集到一个列表中。如果给出了expected_length
且长度不匹配,则会引发异常。当然,在直接迭代比先将元素收集到列表中更好的情况下,您应该直接使用
space.iter()
和space.next()
。
-
unpacktuple
(w_tuple[, expected_length=None])¶ 等效于
unpackiterable()
,但仅适用于元组。
-
callable
(w_obj)¶ 实现内置的
callable()
。
应用程序级别对象的创建¶
-
wrap
(x)¶ 已弃用!最终此方法应该消失。 返回一个包装对象,它引用解释器级别对象
x
。这可以用于简单的不变对象(整数、字符串等)以创建一个新的包装对象,或者用于W_Root
的实例以获得对它们的应用程序级别可见的引用。例如,字节码解释器的大多数类都子类化了W_Root
,并且可以以这种方式直接暴露给应用程序级别代码 - 函数、帧、代码对象等。
-
newint
(i)¶ 创建一个包含整数值的包装对象。 newint 创建一个类型为 W_IntObject 的对象。
-
newlong
(l)¶ 创建一个包含整数值的包装对象。与 newint 的主要区别在于参数的类型(它是 rpython.rlib.rbigint.rbigint)。在 PyPy3 中,此方法将返回一个
int
(PyPy2 返回一个long
)。
-
newbytes
(t)¶ 给定的参数是一个 rpython 字节串。创建一个类型为
bytes
的包装对象(在 PyPy2 和 PyPy3 上都是)。
-
newtext
(t)¶ 给定的参数是一个 rpython 字节串。创建一个类型为
str
的包装对象。在 PyPy3 上,这将返回一个包装的 Unicode 对象。该对象将保存 t 的 utf-8-nosg 解码值。“utf-8-nosg” 编码器在这里使用与 Python 2 或 Python 3 中实现的“utf-8” 略有不同:它被定义为 utf-8,不包含对代理字符的任何特殊处理。它们使用与编码范围从'\u0800'
到'\uffff'
的任何字符相同的三个字节序列进行编码。PyPy2 将返回一个字节串对象。不会应用任何编码/解码步骤。
-
newtuple
([w_x, w_y, w_z, ...])¶ 从解释器级包装对象列表创建一个新的包装元组。
-
newlist
([..])¶ 从解释器级包装对象列表创建一个包装的
list
。
-
newdict
()¶ 返回一个新的空字典。
-
newslice
(w_start, w_end, w_step)¶ 创建一个新的切片对象。
-
newunicode
(ustr)¶ 从 rpython Unicode 字符串创建一个 Unicode 字符串。此方法可能很快消失,并被 :py:function::newutf8 替换。
-
newutf8
(bytestr)¶ 从 rpython 字节串创建一个 Unicode 字符串,以“utf-8-nosg” 解码。在 PyPy3 上,它与 :py:function::newtext 相同。
可以在 pypy/interpeter/baseobjspace.py 和 pypy/objspace/std/objspace.py 中找到更多空间操作。
从应用程序级到解释器级的转换¶
-
unwrap
(w_x)¶ 返回
w_x
的解释器级等效项 - 仅用于测试,因为此方法不是 RPython,因此无法翻译!在大多数情况下,您应该使用下面描述的函数。
-
is_true
(w_x)¶ 返回一个解释器级布尔值 (
True
或False
),它给出包装对象w_x
的真值。这是一个特别重要的操作,因为它对于实现语言中的 if 语句(或者更确切地说,为了严谨,实现 if 语句编译成的条件分支字节码)是必要的。
-
int_w
(w_x)¶ 如果
w_x
是一个应用程序级别的整数或长整数,并且可以无溢出地转换为整数,则返回一个解释器级别的整数。否则,将引发TypeError
或OverflowError
。
-
bigint_w
(w_x)¶ 如果
w_x
是一个应用程序级别的整数或长整数,则返回一个解释器级别的rbigint
。否则,将引发TypeError
。
-
ObjSpace.
bytes_w
(w_x)¶ 接收一个应用程序级别的
bytes
(在 PyPy2 中等于 str)并返回一个 rpython 字节字符串。
-
ObjSpace.
text_w
(w_x)¶ PyPy2 接收一个
str
并返回一个 rpython 字节字符串,或者接收一个unicode
并使用系统默认编码返回一个 rpython 字节字符串。在 PyPy3 中,它接收一个
str
并将返回一个 utf-8 编码的 rpython 字符串。
-
str_w
(w_x)¶ 已弃用。请改用 text_w 或 bytes_w 如果
w_x
是一个应用程序级别的字符串,则返回一个解释器级别的字符串。否则,将引发TypeError
。
-
unicode_w
(w_x)¶ 接收一个应用程序级别的 :py:class::unicode 并返回一个解释器级别的 unicode 字符串。此方法可能很快就会消失,并被 :py:function::text_w 替换。
-
float_w
(w_x)¶ 如果
w_x
是一个应用程序级别的浮点数、整数或长整数,则返回一个解释器级别的浮点数。否则,将引发TypeError
(或:py:exc:OverflowError,对于非常大的长整数)。
-
getindex_w
(w_obj[, w_exception=None])¶ 调用
index(w_obj)
。如果生成的整数或长整数对象可以转换为解释器级别的int
,则返回该值。否则,如果w_exception
为 None,则返回一个钳位结果,否则在应用程序级别引发异常。(如果
w_obj
无法转换为索引,index()
将引发应用程序级别的TypeError
。)
-
interp_w
(RequiredClass, w_x[, can_be_None=False])¶ 如果
w_x
是给定字节码解释器类的包装实例,则解包它并返回它。如果can_be_None
为True
,则包装的None
也被接受并返回解释器级别的None
。否则,将引发一个OperationError
,该错误封装了一个带有友好错误消息的TypeError
。
-
interpclass_w
(w_x)¶ 如果
w_x
是字节码解释器类的包装实例 - 例如Function
、Frame
、Cell
等 - 则返回解包后的实例。否则返回None
。
数据成员¶
-
space.
builtin
¶ 包含内置函数的
Module
。
-
space.
sys
¶ The
sys
Module
。
-
space.
w_None
¶ ObjSpace 的
None
实例。
-
space.
w_True
¶ ObjSpace 的
True
实例。
-
space.
w_False
¶ ObjSpace 的
False
实例。
-
space.
w_Ellipsis
¶ ObjSpace 的
Ellipsis
实例。
-
space.
w_NotImplemented
¶ ObjSpace 的
NotImplemented
实例。
-
space.
w_int
¶ -
space.
w_float
¶ -
space.
w_long
¶ -
space.
w_tuple
¶ -
space.
w_str
¶ -
space.
w_unicode
¶ -
space.
w_type
¶ -
space.
w_instance
¶ -
space.
w_slice
¶ Python 最常见的基本类型对象。
-
space.w_[XYZ]Error
Python 的内置异常类 (
KeyError
,IndexError
等)。
-
ObjSpace.
MethodTable
¶ 包含
(method_name, symbol, number_of_arguments, list_of_special_names)
元组的列表,用于接口的常规部分。注意 元组是解释器级别的。
-
ObjSpace.
BuiltinModuleTable
¶ 内置模块名称列表。
-
ObjSpace.
ConstantTable
¶ 对象空间应定义的常量名称列表。
-
ObjSpace.
ExceptionTable
¶ 异常类名称列表。
-
ObjSpace.
IrregularOpTable
¶ 具有不规则 API(接受和/或返回未包装对象)的方法名称列表。
标准对象空间¶
简介¶
标准对象空间 (pypy/objspace/std/) 是 CPython 对象库(发行版中的 Objects/
子目录)的直接等效项。它是用更低级的语言实现的常见 Python 类型的实现。
标准对象空间定义了一个抽象父类 W_Object
以及子类,如 W_IntObject
、W_ListObject
等。包装对象(字节码解释器主循环的“黑盒”)是这些类之一的实例。当主循环调用两个包装对象 w1
和 w2
之间的操作(如加法)时,标准对象空间会进行一些内部调度(类似于 CPython 中的 Object/abstract.c
),并调用能够执行该操作的适当 W_XYZObject
类的某个方法。
操作本身是用 RPython 允许的原语完成的,结果被构造为一个包装对象。例如,将以下整数加法的实现与 Object/intobject.c
中的 int_add()
函数进行比较
def add__Int_Int(space, w_int1, w_int2):
x = w_int1.intval
y = w_int2.intval
try:
z = ovfcheck(x + y)
except OverflowError:
raise FailedToImplementArgs(space.w_OverflowError,
space.wrap("integer addition"))
return W_IntObject(space, z)
这对于整数对象来说似乎是很多工作(为什么将它们包装到 W_IntObject
实例中,而不是使用普通整数?),但通过以相同的方式包装所有对象(从简单的整数到更复杂类型),代码保持简单易读。
(有趣的是,上面的明显优化实际上已经在 PyPy 中实现了,但不是在这个级别硬编码的——参见 标准解释器优化。)
对象类型¶
pypy/objspace/std/ 包的大部分内容定义并实现了 Python 标准内置对象类型的库。每个类型 xxx
(int
、float
、list
、tuple
、str
、type
等) 通常在模块 xxxobject.py
中实现。
当存在时,W_AbstractXxxObject
类是抽象基类,主要定义了 Python 级类型对象上的外观。然后,实际的实现作为子类存在,称为 W_XxxObject
或某些变体,用于我们有多种不同实现的情况。例如,pypy/objspace/std/bytesobject.py 定义了 W_AbstractBytesObject
,其中包含构建 str
应用级类型所需的一切;并且存在子类 W_BytesObject
(通常的字符串)和 W_Buffer
(针对重复添加进行调整的特殊实现,位于 pypy/objspace/std/bufferobject.py 中)。对于像列表和字典这样的可变数据类型,我们只有一个类 W_ListObject
或 W_DictMultiObject
,它对真实数据和策略进行间接引用;策略可以随着对象内容的变化而改变。
从用户的角度来看,即使存在多个 W_AbstractXxxObject
子类,这也是不可见的:在应用级,它们仍然都是完全相同 Python 类型的实例。PyPy 知道(例如)其解释器级 W_BytesObject
实例的应用级类型是 str,因为 W_BytesObject
中有一个 typedef
类属性,它指向来自 pypy/objspace/std/bytesobject.py 的字符串类型规范;字符串的所有其他实现都使用来自 pypy/objspace/std/bytesobject.py 的相同 typedef
。
有关相同 Python 类型的多种实现的其他示例,请参阅 标准解释器优化。