4

I want to make my code more (memory-)efficient. Right now we have a lot of functions that take an iterable as parameter like:

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

and sometimes we have to provide it an empty list to do its work properly: foo(14,25,[]). The problem is that each time a new list is constructed: it requires to allocate on the heap, and a list seems to 64 bytes of memory (on my own machine, tested with sys.getsizeof([])) whereas the empty tuple only takes a (potentially one time) 48 bytes.

I was therefore wondering whether the empty tuple is a constant. Since tuples are immutable, one can easily make the tuple with length 0 (so ()) a constant in the program. This would decrease the "construction time" (well there is none since it only would set a reference to the constant) and reduce the amount of memory allocated.

My question is whether there are guarantees regarding the Python interpreter (that is any popular interpreter) that the empty tuple is indeed a constant such that () does not require construction time nor allocates additional memory.

Testing it with id(..) seems to support the theory that there is indeed only one zero-tuple:

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

but it could be possible that at runtime the Python interpreter forks the tuple for some reason.

Martijn Pieters
  • 1,048,767
  • 296
  • 4,058
  • 3,343
Willem Van Onsem
  • 443,496
  • 30
  • 428
  • 555
  • http://stackoverflow.com/q/38328857/2301450 – vaultah Feb 01 '17 at 15:18
  • @vaultah: the question was not why. I think the question makes clear that I have an idea how it works behind the curtains. The question is whether it **always** holds that `() is ()`. – Willem Van Onsem Feb 01 '17 at 15:19
  • I think Jim's answer covers that too? – vaultah Feb 01 '17 at 15:26
  • @vaultah: yes but the last time I went to a doctor my eyes were ok and I see *duplicate **question***, not *duplicate **answer*** :) Unfortunately Belgian education only provides the opportunity to study five languages in secondary school, so I cannot exclude the possibility that the interpretation is simply wrong. – Willem Van Onsem Feb 01 '17 at 15:28
  • 2
    @WillemVanOnsem: if the answers to another question answer this one too, then the duplicate is fine. Jim's answer certainly echoes mine. – Martijn Pieters Feb 01 '17 at 15:29

1 Answers1

13

In CPython, the empty tuple is a singleton. Only one copy is created, ever, then reused whenever you use () or use tuple() on an empty generator.

The PyTuple_new() function essentially does this:

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

So if the tuple size is 0 (empty) and free_list[0] object exists (the existing empty tuple singleton), just use that.

See How is tuple implemented in CPython? for more details on free_list; CPython will also re-use already-created tuple instances up to length 20.

This is an implementation detail. Other implementations (Jython, IronPython, PyPy) do not have to do the same.

Martijn Pieters
  • 1,048,767
  • 296
  • 4,058
  • 3,343