Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Does tuple() copy the elements of the argument?

Tags:

python

tuples

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"?

like image 251
UndefinedBehavior Avatar asked Feb 14 '23 22:02

UndefinedBehavior


2 Answers

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])
like image 161
poke Avatar answered Feb 23 '23 01:02

poke


Yes. I think answer to both of your questions are a "yes". When you create a new tuple from an existing iterable, it will simply copy each item and add it to the new tuple object you are creating. Since variables in python are actually names referencing objects, the new tuple you are creating will actually hold references to the same objects as the iterable.

I think this question on variable passing will be helpful.

like image 38
tayfun Avatar answered Feb 22 '23 23:02

tayfun