List Multiplication: repeat multiple elements and deference

Question:

I’ve found numerous solutions on how to repeat a List of Lists while flattening the repeated elements, like so:

[[1,2] for x in range(3)]
: [[1, 2], [1, 2], [1, 2]]

However, I actually have a list of objects that need to be repeated in-line in the List, like so:

mylist = [var1, var2, var1, var2, va1, var2]

without the extra inner list, and importantly, var1 should be copied, not referenced, such that changes to mylist[0] will not also change mylist[2] & mylist[4] etc.
Other solutions regarding lists only still leave the list elements as “pointers”, meaning editing one element actually alters all the repeats of that element in the list.

Is there a readable one-liner for using multiplication/comprehension to do this while removing the “pointers” in the list?

This is an operation users may have to do often with my class and a for() loop will make construction of their list much less readable. I’m already sad that we can’t just use [var1, var2] * 30 without overloading __mult__, which I’m trying to avoid. That would have made their code so readable.


For example, the following use of deepcopy() is not good enough, as the objects are referenced and thus unexpectedly altered

>>> obj1=[1]; obj2=[200]
>>> a=deepcopy( 3*[obj1, obj2] )
>>> a
[[1], [200], [1], [200], [1], [200]]
>>> a[0][0]=50
>>> a
[[50], [200], [50], [200], [50], [200]]

the 50 propagated throughout the list, rather than changing only the first element.

Asked By: Demis

||

Answers:

You need

import copy
[copy.copy(y) for x in range(3) for y in [var1, var2]]

Or shallow copy is not enough

[copy.deepcopy(y) for x in range(3) for y in [var1, var2]]
Answered By: gzc

I’m not quite sure what behavior you’re looking for. Depending on what you want, one of these two options might be right:

In [0]: from itertools import chain

In [1]: from copy import deepcopy

In [2]: [deepcopy(x) for x in 3*[var1, var2]]
Out[2]: [[1, 2], [3, 4], [1, 2], [3, 4], [1, 2], [3, 4]]

In [3]: list( chain( *(3*[var1, var2]) ) )
Out[3]: [1, 2, 3, 4, 1, 2, 3, 4, 1, 2, 3, 4]
Answered By: Stuart Berg
Categories: questions Tags: ,
Answers are sorted by their score. The answer accepted by the question owner as the best is marked with
at the top-right corner.