Python Lists: Creating, Indexing and Slicing

A list is an ordered, changeable sequence that can hold anything. Indexing, slicing and slice assignment cover most of what you will ever do with one.

Creating a list

empty = []
empty_too = list()

numbers = [1, 2, 3, 4]
names = ["Meera", "Arun"]
mixed = [1, "two", 3.0, True, None, [5, 6]]     # any types, including lists

from_string = list("abc")           # ['a', 'b', 'c']
from_range = list(range(5))         # [0, 1, 2, 3, 4]
repeated = [0] * 5                  # [0, 0, 0, 0, 0]

A list is ordered (positions are meaningful and stable), mutable (it can be changed in place), and allows duplicates. Those three properties decide when a list is the right choice.

Indexing

items = ["a", "b", "c", "d", "e"]

print(items[0])      # a
print(items[2])      # c
print(items[-1])     # e   last
print(items[-2])     # d
# print(items[10])   # IndexError: list index out of range
  'a'  'b'  'c'  'd'  'e'
   0    1    2    3    4
  -5   -4   -3   -2   -1

Changing an item

items = ["a", "b", "c"]
items[1] = "B"
print(items)         # ['a', 'B', 'c']

This is the difference from a string. A list supports item assignment because it is mutable.

Slicing

items = [0, 1, 2, 3, 4, 5, 6, 7]

print(items[2:5])       # [2, 3, 4]     stop is excluded
print(items[:3])        # [0, 1, 2]
print(items[5:])        # [5, 6, 7]
print(items[:])         # a shallow copy of the whole list
print(items[-3:])       # [5, 6, 7]
print(items[::2])       # [0, 2, 4, 6]
print(items[::-1])      # [7, 6, 5, 4, 3, 2, 1, 0]  reversed
print(items[10:20])     # []  slicing never raises

Slice assignment

A slice can be assigned to, which lists allow and strings do not. It can replace, insert or delete, and the lengths do not have to match.

items = [0, 1, 2, 3, 4]

items[1:3] = ["a", "b"]          # replace, same length
print(items)                     # [0, 'a', 'b', 3, 4]

items[1:3] = ["x"]               # replace with fewer: the list shrinks
print(items)                     # [0, 'x', 3, 4]

items[1:1] = ["p", "q"]          # empty slice: insert without removing
print(items)                     # [0, 'p', 'q', 'x', 3, 4]

items[1:3] = []                  # delete a range
print(items)                     # [0, 'x', 3, 4]

items[:] = [9, 9]                # replace the CONTENTS, keeping the same object
print(items)                     # [9, 9]
items[:] = other and items = other look similar and behave completely differently. The first changes the existing list, so every other name pointing at it sees the change. The second rebinds only this name.

Length, membership and counting

items = ["a", "b", "a", "c"]

print(len(items))            # 4
print("a" in items)          # True
print("z" not in items)      # True
print(items.count("a"))      # 2
print(items.index("b"))      # 1
# print(items.index("z"))    # ValueError

Iterating

items = ["a", "b", "c"]

for item in items:
    print(item)

for index, item in enumerate(items):
    print(index, item)

for item in reversed(items):
    print(item)

for item in sorted(items, reverse=True):
    print(item)

Lists hold references

inner = [1, 2]
outer = [inner, inner]

inner.append(3)
print(outer)        # [[1, 2, 3], [1, 2, 3]] - both entries are the same object

A list does not contain objects; it contains references to them. This is why the repetition trick for building a grid fails:

grid = [[0] * 3] * 2       # WRONG
grid[0][0] = 9
print(grid)                # [[9, 0, 0], [9, 0, 0]] - one row, referenced twice

grid = [[0] * 3 for _ in range(2)]     # correct: a fresh row each time
grid[0][0] = 9
print(grid)                # [[9, 0, 0], [0, 0, 0]]

Useful built ins

numbers = [4, 1, 9, 3]

print(len(numbers))           # 4
print(sum(numbers))           # 17
print(min(numbers), max(numbers))     # 1 9
print(sorted(numbers))        # [1, 3, 4, 9] - a NEW list
print(list(reversed(numbers)))# [3, 9, 1, 4]
print(any(n > 8 for n in numbers))    # True
print(all(n > 0 for n in numbers))    # True

Unpacking

point = [3, 7]
x, y = point
print(x, y)             # 3 7

first, *rest = [1, 2, 3, 4]
print(first, rest)      # 1 [2, 3, 4]

head, *middle, tail = [1, 2, 3, 4, 5]
print(middle)           # [2, 3, 4]

a, b = [1, 2]
a, b = b, a             # swap
print(a, b)             # 2 1

Common mistakes

  • Assuming items[2:5] includes index 5.
  • Using [[0] * 3] * 2 to build a grid.
  • Assuming b = a copies a list.
  • Calling .index() on a value that may be missing, without catching ValueError.
  • Indexing out of range instead of slicing, when an empty result would have been fine.
  • Confusing items[:] = other with items = other.

Best practices

  • Use a list when order matters and the contents will change; use a tuple when they will not.
  • Use negative indexes rather than len(items) - 1.
  • Use slicing rather than a loop to take a portion.
  • Build nested lists with a comprehension, never with repetition.
  • Prefer in over .index() when you only need to know whether something is present.

Practice

  1. Given list(range(10)), produce the even values, the last three, and the whole list reversed, using slices only.
  2. Insert two items into the middle of a list without using insert.
  3. Explain the difference between items[:] = [1, 2] and items = [1, 2] when another name refers to the same list.
  4. Build a 3 by 4 grid of zeros correctly, then set one cell and prove the others did not change.
  5. Write a function returning the second largest distinct value in a list.

Conclusion

Lists are ordered, mutable sequences of references. Indexing reaches one item, slicing reaches a range and never raises, and slice assignment can replace, insert or delete in one statement. The reference nature is what makes copying and grid building worth thinking about.

Written by Lorens Mishra

Default administrator account created by the installer.

Continue reading

All Python notes →
Python

Trees and Graphs

A tree is a graph with no cycles and one root. Both are walked with the same two strategies - depth first with a stack, breadth first with a queue.

Read more

Discussion

0 comments
Sign in to join the discussion.

No comments yet. Be the first to say something.