Copying lists in python
Question: I am relatively new to Python. I am trying to come up with a function that
takes a list, adds +1 to a value at random in that list, and then places a new
list with the modified value as a new index.

For instance, if I have

    
    
    blank=[]
    list_one=[1,2,3,4,5] # 
    

The possible outcome might be

    
    
    blank=[ [1,2,3,4,5], [1,3,3,4,5],[1,3,3,4,6],[2,3,3,4,6],[2,4,3,4,6] ]
    

So the function takes blank[0], copies and modifies it, and returns it as
blank[1]. Similarly, the function takes blank[1], copies it and modifies it,
and returns it as blank[2]

This is my code:

    
    
    import random
    list_one=[1,2,3,4,5]
    def new_function(value):
        for i in range(1,value):
            list_copy=list_one[:]
            blank.append(list_copy)
            x=random.choice(blank[i])
            y=blank[i].index(x)
            blank[i][y]=x+1
        return blank
    
    print new_function(4) 
    """Yields [ [1,2,3,4,5],[1,3,3,4,5],[2,2,3,4,5],[1,2,4,4,5] ] 
       (this is the list, blank)"""
    

my problem is that blank[1], blank[2], and blank[3] are all modifications of
blank[0], when each indexed list should be a modification of the previous
indexed list.

What am I doing wrong here???


Answer: The issue is that you always copy the original list, not the new one. This is
easily solved by using the same name for the new list, thus, when the loop
comes round again, the new list is copied:

    
    
    import random
    
    def randomly_increment(seq, n):
        for _ in range(n):
            x = random.randrange(len(seq))
            seq = list(seq)
            seq[x] += 1
            yield seq
    

Which I believe works as intended:

    
    
    >>> list(randomly_increment([1, 2, 3, 4, 5], 4))
    [[1, 2, 4, 4, 5], [1, 2, 4, 5, 5], [1, 2, 4, 5, 6], [1, 2, 4, 6, 6]]
    

Other changes:

  * Rather than building a list, this is a generator, which is generally more flexible and easier to read/write. If you need a list, then wrap the call with `list()` as above.
  * Rather than making a random choice, then finding it's place to change it, it makes more sense to pick a place, and change it. This also avoids the issue where `seq.index()` will return the first value matching the given one, not necessarily the 'picked' one.
  * Using `list(seq)` to copy over `seq[:]`, as noted in my comment. This is more readable.

