18

To make my program more beautiful instead of ugly, I am trying to find a more pythonic way of adding a single value multiple times to a list. I now use a loop, but I create a variable I do not use.

l = []; n = 5; v = 0.5

for i in xrange(n):
    l.append(v)

Any ideas?

Bsje
  • 223
  • 1
  • 2
  • 6
  • That would define l, not append to it. If l already holds values they would be lost. – Boo Dec 06 '13 at 14:32
  • Thanks all, Lattyware for the most general answer, although I will use Boo's solution in this specific case ;) – Bsje Dec 06 '13 at 14:50

4 Answers4

51

To add v, n times, to l:

l += n * [v]
Boo
  • 707
  • 5
  • 6
11

Try using list.extend and the multiply operator for lists

l.extend([v] * n)
Nils Werner
  • 34,832
  • 7
  • 76
  • 98
  • 4
    Note that this will produce a list of `[v, v, v...]` `n` times, which is fine if the value is immutable, but could cause unexpected behaviour if the value is mutable and you expect them to be independent. – Gareth Latty Dec 06 '13 at 14:31
  • 1
    Note that if `v` is a mutable object then it can lead to undesired results. – Ashwini Chaudhary Dec 06 '13 at 14:31
  • In case *you know that `v` is mutable* you should use `[v.copy()] * n` instead. – Nils Werner Dec 06 '13 at 14:34
  • 1
    @NilsWerner That will not work. It will copy the value once, and then make a list of `n` references to that copy. – Gareth Latty Dec 06 '13 at 14:36
  • Oh, you are right. Wouldn't have expected that... – Nils Werner Dec 06 '13 at 14:37
  • @NilsWerner It's because the value is evaluated as a literal, then placed into a list. By the time you are multiplying that list, it's just a list containing a reference to an object - Python doesn't know how to copy that item even if it wanted to (`__copy__()` is a good guess, but there is no guarantee it's implemented or possible). The issue is expecting `*` to re-evaluate the expression, which it doesn't do. It just copies a reference. It's more obvious if you think of it as `new = v.copy()` `[new] * n` - which is exactly the same. – Gareth Latty Dec 06 '13 at 14:44
10

The most general answer to this is to use list.extend() and a generator expression:

l.extend(generate_value() for _ in range(n))

This will add a value n times. Note that this will evaluate generate_value() each time, side-stepping issues with mutable values that other answers may have:

>>> [[1]] * 5
[[1], [1], [1], [1], [1]]
>>> _[0].append(1)
>>> _
[[1, 1], [1, 1], [1, 1], [1, 1], [1, 1]]
>>> [[1] for _ in range(5)]
[[1], [1], [1], [1], [1]]
>>> _[0].append(1)
>>> _
[[1, 1], [1], [1], [1], [1]]

When using the multiplication method, you end up with a list of n references to the same list. When you change it, you see the change in every element of the list - as they are all the same.

When using a generator expression or list comprehension, a new list is created for each sub-item, so each item is a different value. Modifying one only affects that one.

Obviously, in your example, the values are immutable, so this doesn't matter - but it's worth remembering for different cases, or if the values might not be immutable.

Gareth Latty
  • 86,389
  • 17
  • 178
  • 183
  • 1
    As an alternative to `generate_value()`; in most cases you can also use `copy.deepcopy()` – Lie Ryan Dec 06 '13 at 15:02
  • @LieRyan 'In most cases' is strong - In most cases, you'll probably just be putting a constructor call or a literal there, so copying wouldn't be necessary. `copy.deepcopy()` also only works on things that implement `__deepcopy__()`, which isn't a guarantee. `generate_value()` is a place-holder designed to show that anything that produces a value could be used - including, but not limited to, `copy.deepcopy()`. – Gareth Latty Dec 06 '13 at 15:03
2

Try this

n = 5
v = 0.5
l = [v]*n 
JoeC
  • 1,850
  • 14
  • 12