0

I have looked for similar discussions, but I haven't been able to find any - so here goes:

Basically, I want to have a list, say, preallocated to 10 values:

mylist = [ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ]

Then, I want to define, say, two sets of values, which I expect, the mylist will be "switching" between in my code most of the time; say:

valsA = ( 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 )
valsB = ( 9, 8, 7, 6, 5, 4, 3, 2, 1, 0 )

Since these are predefined sets of values, no point in defining them as lists, so they are defined as tuples.

Now, I could in principle just do:

# some code running here ...

# switch mylist to valsA:
mylist = valsA

# some more code using mylist running here ...

# switch mylist to valsB:
mylist = valsB

# some more code using mylist running here ...

... however, the problem is, that just by direct assignment, mylist then becomes identifier for the tuple:

>>> valsA = ( 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 )
>>> valsB = ( 9, 8, 7, 6, 5, 4, 3, 2, 1, 0 )
>>> mylist = [ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ]
>>> id(valsA)
123145300863808
>>> hex(id(valsA))
'0x6fffffe9eb40'
>>> hex(id(valsB))
'0x6fffffeb81c0'
>>> hex(id(mylist))
'0x6fffffea9bc0'
>>> mylist = valsA
>>> hex(id(mylist))
'0x6fffffe9eb40'
>>> type(mylist)
<class 'tuple'>

... and so, after such an assignment, if my code wants to change a single slot/item/entry in mylist, it won't be able to, since it is now an immutable tuple:

>>> mylist
(0, 1, 2, 3, 4, 5, 6, 7, 8, 9)
>>> mylist[2] = 15
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: 'tuple' object does not support item assignment

So, instead, what I'm looking for an efficient way to copy the values of the tuple - say, the most obvious approach for me would be:

>>> mylist = [ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ] # reset

>>> for tidx, tval in enumerate(mylist): mylist[tidx] = valsA[tidx]
...
>>> print(mylist)
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]

... which then allows for changing individual items in mylist:

>>> mylist[2] = 15
>>> print(mylist)
[0, 1, 15, 3, 4, 5, 6, 7, 8, 9]

... however, then I have a Python-level loop I have to go through, which from earlier experience, is not necessarily the fastest way to do things; and also, it is not necessarily the most readable (although I could always wrap it in a function/method - but then I have an overhead of function calls).

Is there a more efficient way to copy values from a tuple to a list, than running a for loop? Say, maybe there is something like (pseudocode) mylist.fill(valsA) method, or some other approach?

sdbbs
  • 4,270
  • 5
  • 32
  • 87
  • 2
    Does this answer your question? [Convert tuple to list and back](https://stackoverflow.com/questions/16296643/convert-tuple-to-list-and-back) – Amongalen Dec 01 '21 at 10:03
  • Thanks @Amongalen - not really sure; I'm sure `mylist = list(valsA)` will change the ID of the structure `mylist` is pointing to, but I cannot tell yet whether it is relevant to my problem; so I'd focus on whether the overhead of calling `list()` is more (or less) than running a loop that copies values as in this question; but I cannot see where the linked question discusses that. – sdbbs Dec 01 '21 at 10:11
  • 1
    I haven't tested it myself but I'd guess the build-in method is as performant as you can get. Also are you sure the performance matters here? Be wary of premature optimization. – Amongalen Dec 01 '21 at 10:18

1 Answers1

0

Thanks to the comment by @Amongalen, from the linked question, I recalled "casting" to list, that is mylist = list(valsA); but I was not sure whether it is faster than just a loop; I just tested that, and it seems that it is:

>>> import timeit

>>> timeit.timeit("mylist = list(valsB)", number=10000, globals=globals())
0.001488900000367721

>>> timeit.timeit("for tidx, tval in enumerate(mylist): mylist[tidx] = valsA[tidx]", number=10000, globals=globals())
0.009989700000005541

So, yeah, mylist = list(valsA) is faster - and I guess, it is most efficient to switch between values in this way; although as caveat, the ID of the object mylist points to, will change.

sdbbs
  • 4,270
  • 5
  • 32
  • 87