Does tuple() copy the elements of the argument?

python, tuples

Solution

`tuple` will iterate the sequence and copy the values. The underlying sequence will be not stored to actually keep the values, but the tuple representation will replace it. So yes, the conversion to a tuple is actual work and not just some nesting of another type.

You can see this happening when converting a generator:

>>> def gen ():
        for i in range(5):
            print(i)
            yield i
>>> g = gen()
>>> g
<generator object gen at 0x00000000030A9B88>
>>> tuple(g)
0
1
2
3
4
(0, 1, 2, 3, 4)

As you can see, the generator is immediately iterated, making the values generate. Afterwards, the tuple is self-contained, and no reference to the original source is kept. For reference, `list()` behaves in exactly the same way but creates a list instead.

The behaviour that 275365 pointed out (in the now deleted answer) is the standard copying behaviour of Python values. Because everything in Python is an object, you are essentially only working with references. So when references are copied, the underlying object is not copied. The important bit is that non-mutable objects will be recreated whenever their value changes which will not update all previously existing references but just the one reference you are currently changing. That’s why it works like this:

>>> source = [[1], [2], [3]]
>>> tpl = tuple(source)
>>> tpl
([1], [2], [3])
>>> tpl[0].append(4)
>>> tpl
([1, 4], [2], [3])
>>> source
[[1, 4], [2], [3]]

`tpl` still contains a reference to the original objects within the `source` list. As those are lists, they are mutable. Changing a mutable list anywhere will not invalidate the references that exist to that list, so the change will appear in both `source` and `tpl`. The actual source list however is only stored in `source`, and `tpl` has no reference to it:

>>> source.append(5)
>>> source
[[1, 4], [2], [3], 5]
>>> tpl
([1, 4], [2], [3])

Problem

In python, does the built-in function `tuple([iterable])` create a tuple object and fill it with copies of the elements of "iterable", or does it create a tuple containing references to the already existing objects of "iterable"?

Original source

Related problems