Scrollable Nav Bar

Python Lists

Lists are one of the most important data structures in Python. They let you store multiple values in a single variable, keep those values in order, and easily add, remove, and update items as your program runs. If you already understand strings, you’ll feel at home with lists—because many of the same ideas (like indexing and slicing) work in almost the same way.


List

A list is an ordered collection of values. You create a list using square brackets [], and items are separated by commas.

Example:

my_list = [1, 2, 3, 4, 5]
print(my_list)

Lists can store any type of data: numbers, strings, booleans, even other lists.

Example :

mixed = [10, "Python", True, 3.14]
print(mixed)

[Creating and printing a list]


Indexing lists: accessing one item

Lists are zero-indexed, meaning the first item is at index 0.

Example :

my_list = ["one", "two", "three", "four", "five"]
print(my_list[0])  # one
print(my_list[3])  # four

You can also use negative indexes to count from the end.

Example:

print(my_list[-1])  # five
print(my_list[-2])  # four

[ Indexing with positive and negative indexes]


Slicing lists: extracting a portion

Slicing lets you extract a sub-list. The basic slice format is:

my_list[start:end]
  • start is included
  • end is excluded

Example :

my_list = ["one", "two", "three", "four", "five"]
print(my_list[2:])     # from index 2 to the end
print(my_list[1:4])    # indexes 1, 2, 3

This works just like slicing strings, which is why lists and strings often feel similar in Python.

[ Slicing output examples]


Slicing with a step: every other item

A powerful extension of slicing is the step value:

my_list[start:end:step]

The step controls how many positions to jump each time.

Example:

my_list = ["one", "two", "three", "four", "five", "six"]

print(my_list[0:6:2])  # every 2nd item
print(my_list[0:6:3])  # every 3rd item

If you’re slicing from the beginning to the end, you can omit start and end.

Example:

print(my_list[::2])

This reads as: “from start to end, take every 2nd item.”

[Step slicing with different step values]


Building long lists quickly with range()

Typing long lists by hand is boring and error-prone. Python gives you the range() function to generate sequences of numbers.

Example:

for i in range(5):
    print(i)

range() is a sequence type that is commonly used in loops. When you need an actual list, you can convert it using list().

Example:

numbers = list(range(10))
print(numbers)

Now you can slice it like any other list.

Example :

numbers = list(range(100))
print(numbers[::2])   # every other number
print(numbers[::5])   # every 5th number
print(numbers[::10])  # every 10th number

[Creating a long list with range and slicing it]


Negative step: slicing backwards

A negative step means “move backwards.” This is an extremely handy trick.

Example:

numbers = list(range(20))
print(numbers[::-1])   # reversed list
print(numbers[::-2])   # reversed, every other item
print(numbers[::-10])  # reversed, jump by 10

This concept is worth remembering because it shows up everywhere in real-world Python.

[Negative step slicing examples]


Modifying lists: append() and insert()

So far, slicing and indexing have been about reading data. Now let’s update a list.

Add an item at the end with append()

Example:

my_list = [1, 2, 3, 4]<br>my_list.append(5)<br>print(my_list)

append() adds a single item to the end of the list.

Insert an item at a specific position with insert()

Example :

my_list = [1, 2, 3, 4]
my_list.insert(2, 99)  # insert 99 at index 2
print(my_list)

insert(index, value) shifts items to the right to make room.

[ append vs insert output]


Removing items: remove() and pop()

Python gives you multiple ways to remove list elements. Which one you choose depends on what you have: a value or an index.

Remove by value with remove()

Example:

my_list = [1, 2, 3, 2, 4]
my_list.remove(2)
print(my_list)  # removes the first 2

remove(value) deletes the first matching item.

One important warning: if the value is not in the list, Python raises an error.

my_list = [1, 2, 3]
# my_list.remove(99)  # ValueError: list.remove(x): x not in list

In real programs, you often protect this with a check.

if 99 in my_list:
    my_list.remove(99)

Remove by index with pop()

pop() removes an item and returns it.

my_list = [1, 2, 3, 4, 5]
last_item = my_list.pop()
print(last_item)  # 5
print(my_list)    # [1, 2, 3, 4]

You can also pop a specific index.

my_list = ["a", "b", "c", "d"]
item = my_list.pop(1)
print(item)     # b
print(my_list)  # ['a', 'c', 'd']

[ remove vs pop output]


Emptying a list by popping in a loop

Sometimes you want to repeatedly remove items until the list becomes empty. A very clean pattern is:

my_list = [1, 2, 3, 4]

while len(my_list):
    print(my_list.pop())

print(my_list)  # []

The key idea here is that len(my_list) becomes 0 when the list is empty, and 0 behaves like False in a condition—so the loop stops automatically.

[while loop popping items until list is empty]


Lists, memory, and copying: why changes sometimes “spread”

This is a topic that surprises many beginners, but it’s essential if you want to avoid confusing bugs.

Consider this code:

a = [1, 2, 3, 4, 5]
b = a

a.append(6)
print(b)

Even though you modified a, the change appears in b. That happens because b = a does not create a new list—it creates a new reference to the same list in memory.

Fix: create a separate list using copy()

If you want b to be a separate list stored independently, make a copy.

a = [1, 2, 3, 4, 5]
b = a.copy()

a.append(6)
print("a:", a)
print("b:", b)

Now a changes, but b stays the same—because it’s a different list in memory.

[Difference between assignment and copy]


Practice

Open a Python notebook (or a .py file) and experiment with these ideas. The goal is to build intuition.

  1. Create a list of 20 numbers using list(range(20)).
  2. Print the first 5 items, then the last 5 items using slicing.
  3. Print every 3rd item using a step.
  4. Print the list in reverse order using slicing.
  5. Add values using append() and insert().
  6. Remove a value using remove() and remove by index using pop().
  7. Create two variables pointing to the same list, modify one, and observe the other.
  8. Repeat the same experiment using copy() and compare the results.

[Your exercise outputs]


Summary

By now, you should be comfortable with what makes lists so useful in Python. You learned how slicing works (including steps and reverse slicing), how to generate large lists quickly using range(), how to modify a list with append() and insert(), and how to remove items safely using remove() and pop(). Most importantly, you saw why list assignment and list copying behave differently—an idea that becomes increasingly important as your programs grow.