Python中的空元组是"常数"

时间:2017-02-01 15:13:21

标签: python memory tuples python-internals

我想让我的代码更有效(内存)效率。现在我们有很多函数将iterable作为参数,如:

def foo(para,meter,iterable):
    #...
    pass

有时我们必须提供一个空列表才能正常工作:foo(14,25,[])。问题是每次构造一个新列表时:它需要在堆上进行分配,并且列表似乎是64字节的内存(在我自己的机器上,使用sys.getsizeof([])进行测试)而只有空元组 需要(可能是一次)48个字节。

因此我想知道空元组是否是常量。由于元组是不可变的,因此可以轻松地使长度为0(因此())的元组在程序中成为常量。这将减少建设时间" (没有,因为它只会设置对常量的引用)并减少分配的内存量。

我的问题是,对于Python解释器(即任何流行的解释器)是否有保证,空元组确实是一个常量,因此()不需要构造时间也不需要分配额外的内存。

使用id(..)进行测试似乎支持这样的理论:确实只有一个零元组:

>>> id(())
140290183798856
>>> a = ()
>>> id(a)
140290183798856

但是有可能在运行时Python解释器出于某种原因分叉元组。

1 个答案:

答案 0 :(得分:8)

在CPython中,空元组是一个单例。永远只创建一个副本,然后在空发生器上使用()或使用tuple()时重复使用。

PyTuple_new() function基本上是这样做的:

if (size == 0 && free_list[0]) {
    op = free_list[0];
    Py_INCREF(op);
    // ...
    return (PyObject *) op;
}

因此,如果元组大小为0(空)且存在free_list[0]对象(现有的空元组单例),则只需使用它。

有关free_list的详细信息,请参阅How is tuple implemented in CPython?; CPython还将重用已经创建的tuple个实例,最长可达20个。

这是实施细节。其他实现(Jython,IronPython,PyPy)也不必这样做。