3
mylist = ["a", "apple", "b", "ball", "c", "cat"]
mylist[6] = "value"
print(mylist)

Error:

IndexError: list assignment index out of range

I remember assigning values by index in javascript, it doesn't work in python?

jamylak
  • 128,818
  • 30
  • 231
  • 230

4 Answers4

14

Python's lists are 0-indexed. You have 6 elements in your list, so you can index them with anything from 0 to 5. Attempting to go beyond those bounds will not work with the normal list type, but it seems you want to use indexing as implicit list-extension.

For that you want a sparse container, and here's a quick implementation that subclasses list.

class SparseList(list):
    def __setitem__(self, index, value):
        """Overrides list's __setitem__ to extend the list
           if the accessed index is out of bounds."""
        sparsity = index - len(self) + 1
        self.extend([None] * sparsity)
        list.__setitem__(self, index, value)

Use this like this:

In [8]: sl = SparseList()

In [9]: print(sl)
[]

In [10]: sl[3] = "hi"

In [11]: print(sl)
[None, None, None, 'hi']

And your specific example:

In [11]: mylist = SparseList(["a", "apple", "b", "ball", "c", "cat"])

In [12]: print mylist
['a', 'apple', 'b', 'ball', 'c', 'cat']

In [13]: mylist[6] = "value"

In [14]: print mylist
['a', 'apple', 'b', 'ball', 'c', 'cat', 'value']

And if you want something a little less self-made, try blist

wkl
  • 77,184
  • 16
  • 165
  • 176
  • Right, so `value` will replace `cat`, but I want to assign a new value at the end (without using append etc..) –  May 17 '12 at 05:47
  • 2
    @SiriusKoder - You mean putting a new value in? Python's lists do not work that way. You would have to make your own wrapper class that implements a sparse list (basically creating a list that would have a bunch of `None` values in it. – wkl May 17 '12 at 05:49
  • @birryree: Is it possible in this way. Use [len] (http://docs.python.org/library/functions.html#len) function on the list, decrement the value by 1 (since Python lists are 0-based) and assign a value to the index? – verisimilitude May 17 '12 at 05:52
  • @jamylak: I think he just wants to assign a value to the last element ie. replace the last element, is it, @SiriusKoder? – verisimilitude May 17 '12 at 05:54
  • 1
    @versimilitude well then he can just use `mylist[-1]` – jamylak May 17 '12 at 05:55
  • 2
    @verisimilitude - he wants a sparse list, which allows assignment to any arbitrary position in the list, even if that position doesn't exist yet as a result of `append`ing. – wkl May 17 '12 at 05:57
  • 1
    @SiriusKoder - See my revised answer for a sparse list implementation that subclasses the built in `list` class of Python and allows Javascript-like list behavior. – wkl May 17 '12 at 05:58
  • Got it. +1 to your suggestions above birrytree :) – verisimilitude May 17 '12 at 05:59
  • @verisimilitude just to clarify, I want to append not replace. –  May 17 '12 at 06:03
  • 2
    For some heavy duty sparse entry work, I would opt to use a dictionary with keys as indexes. This has the advantage of not having to create all the entries in between when accessing an item. – Joel Cornett May 17 '12 at 06:24
5

In python single assignment does not work if the index does not exist. Javascript arrays are "sparse", you can stash a value at any index. Instead, python lists have a defined size, and assignment is only allowed in existing indices.

If you want to add at the end, use mylist.append(value),

jamylak
  • 128,818
  • 30
  • 231
  • 230
1

What you are asking can be done with SparseList as described by birrye. Or you can always use append. In python dictionary though you can have any indexed assignment say,

dic = {}
dic['1'] = 100
dic['2'] = 200

So what you can do is write like this,

list = {}
i = 1 #Your index
list[str(i)] = value #Your value

This might increase the execution time a bit. You will get IndexError exception raised if you reference any unassigned index.

0

You can achieve this by first creating a list of None objects, but it's probably not the best way to do things.

mylist = [None] * 10
mylist[0:5] = ["a", "apple", "b", "ball", "c", "cat"]
mylist[6] = "value"

Alternatively, you could just append elements to the end of the list.

mylist = ["a", "apple", "b", "ball", "c", "cat"]

# create 7th element
mylist += ["value"]

# create 10th element
mylist += [None] * 2 + ["value2"]
grc
  • 22,885
  • 5
  • 42
  • 63
  • You can also slice beyond the range of the list i.e. `mylist[13:13] = [1]`. This causes the assignment to be appended to the end of the list. – Joel Cornett May 17 '12 at 05:57