Cristhian Villegas
Backend11 min read1 views

Python Data Structures: Lists, Tuples, Dictionaries and Sets

Python Data Structures: Lists, Tuples, Dictionaries and Sets

Introduction: why we need data collections

Welcome to part 5 of 10 of our Python course for beginners. So far we have worked with variables that store a single value: a number, a string, a boolean. But in real life, we almost always need to handle groups of data.

Think about a shopping list, the contacts on your phone, or a student's grades. They are all collections of data. Python has 4 main structures to organize data: lists, tuples, dictionaries, and sets. In this article we will learn each one with practical examples.

Python Logo

Lists: your first collection

A list is an ordered collection of elements that you can modify. It is probably the data structure you will use the most in Python. Lists are created with square brackets [].

Creating a list

python
1# List of fruits
2fruits = ["apple", "banana", "orange"]
3print(fruits)  # ['apple', 'banana', 'orange']
4
5# List of numbers
6numbers = [10, 20, 30, 40, 50]
7print(numbers)  # [10, 20, 30, 40, 50]
8
9# Mixed list (different data types)
10mixed = ["hello", 42, True, 3.14]
11print(mixed)  # ['hello', 42, True, 3.14]
12
13# Empty list
14empty = []
15print(empty)  # []

Accessing elements

Each element has a position (index) that starts at 0, not 1. This is very important to remember.

python
1fruits = ["apple", "banana", "orange", "grape"]
2
3# Access by index (starts at 0)
4print(fruits[0])   # apple (first)
5print(fruits[1])   # banana (second)
6print(fruits[3])   # grape (fourth)
7
8# Negative indices (from the end)
9print(fruits[-1])  # grape (last)
10print(fruits[-2])  # orange (second to last)
💡 Tip: Negative indices are very useful. list[-1] always gives you the last element without needing to know how many elements the list has.

Modifying elements

python
1fruits = ["apple", "banana", "orange"]
2
3# Change an element
4fruits[1] = "strawberry"
5print(fruits)  # ['apple', 'strawberry', 'orange']
6
7# Add to the end
8fruits.append("grape")
9print(fruits)  # ['apple', 'strawberry', 'orange', 'grape']
10
11# Remove an element by value
12fruits.remove("strawberry")
13print(fruits)  # ['apple', 'orange', 'grape']
14
15# Remove by index
16del fruits[0]
17print(fruits)  # ['orange', 'grape']

Slicing

You can get a portion of the list using slicing:

python
1numbers = [10, 20, 30, 40, 50, 60]
2
3print(numbers[1:4])   # [20, 30, 40] (index 1 to 3)
4print(numbers[:3])    # [10, 20, 30] (from start to index 2)
5print(numbers[3:])    # [40, 50, 60] (from index 3 to end)
6print(numbers[::2])   # [10, 30, 50] (every other element)

Useful list methods

Lists have many methods that make your life easier. Here are the most important ones:

python
1numbers = [3, 1, 4, 1, 5, 9, 2, 6]
2
3# append() - add to the end
4numbers.append(7)
5print(numbers)  # [3, 1, 4, 1, 5, 9, 2, 6, 7]
6
7# insert() - insert at a specific position
8numbers.insert(0, 99)  # insert 99 at position 0
9print(numbers)  # [99, 3, 1, 4, 1, 5, 9, 2, 6, 7]
10
11# remove() - remove the first occurrence of a value
12numbers.remove(1)  # removes the first 1
13print(numbers)  # [99, 3, 4, 1, 5, 9, 2, 6, 7]
14
15# pop() - remove and return the last element (or one at a given index)
16last = numbers.pop()
17print(last)      # 7
18print(numbers)   # [99, 3, 4, 1, 5, 9, 2, 6]
19
20second = numbers.pop(1)  # remove index 1
21print(second)    # 3
22
23# sort() - sort the list
24numbers.sort()
25print(numbers)  # [1, 2, 4, 5, 6, 9, 99]
26
27# reverse() - reverse the order
28numbers.reverse()
29print(numbers)  # [99, 9, 6, 5, 4, 2, 1]
30
31# len() - find out how many elements it has
32print(len(numbers))  # 7
33
34# in - check if an element exists
35print(5 in numbers)    # True
36print(100 in numbers)  # False
📌 Note: sort() modifies the original list. If you want a sorted copy without modifying the original, use sorted(list).

Tuples: lists that cannot be changed

A tuple is very similar to a list, but with one fundamental difference: it cannot be modified after creation. This is called immutability. Tuples are created with parentheses ().

python
1# Create a tuple
2coordinates = (10, 20)
3print(coordinates)     # (10, 20)
4print(coordinates[0])  # 10
5print(coordinates[1])  # 20
6
7# Tuple with several elements
8colors = ("red", "green", "blue")
9print(colors[1])  # green
10
11# Trying to modify a tuple gives an error
12# colors[0] = "yellow"  # TypeError: 'tuple' object does not support item assignment

When to use tuples instead of lists

  • Data that should not change: geographic coordinates, dates, fixed configurations
  • Dictionary keys: tuples can be keys, lists cannot
  • Functions that return multiple values: Python uses tuples automatically
  • Performance: tuples are slightly faster than lists
python
1# Function that returns multiple values (as a tuple)
2def get_full_name():
3    return "John", "Smith"  # Python creates a tuple automatically
4
5first_name, last_name = get_full_name()  # unpacking
6print(first_name)   # John
7print(last_name)    # Smith
8
9# Tuple as dictionary key
10locations = {
11    (19.43, -99.13): "Mexico City",
12    (40.71, -74.00): "New York"
13}
14print(locations[(19.43, -99.13)])  # Mexico City
⚠️ Watch out: To create a single-element tuple, you need a trailing comma: my_tuple = (42,). Without the comma, Python interprets it as a number in parentheses: (42) is simply 42.

Dictionaries: key-value pairs

A dictionary is a collection that stores data as key: value pairs. It works like a real dictionary: you look up a word (key) and find its definition (value). Dictionaries are created with curly braces {}.

Creating and accessing dictionaries

python
1# Create a dictionary
2person = {
3    "name": "Ana",
4    "age": 25,
5    "city": "Guadalajara"
6}
7
8# Access values by key
9print(person["name"])  # Ana
10print(person["age"])   # 25
11
12# Access with get() (safer, does not error if the key doesn't exist)
13print(person.get("name"))      # Ana
14print(person.get("phone"))     # None (doesn't exist, but no error)
15print(person.get("phone", "Not available"))  # "Not available" (default value)

Adding and modifying

python
1person = {"name": "Ana", "age": 25}
2
3# Add a new key-value pair
4person["email"] = "[email protected]"
5print(person)
6# {'name': 'Ana', 'age': 25, 'email': '[email protected]'}
7
8# Modify an existing value
9person["age"] = 26
10print(person["age"])  # 26
11
12# Delete a key-value pair
13del person["email"]
14print(person)  # {'name': 'Ana', 'age': 26}

Iterating over a dictionary

python
1person = {"name": "Ana", "age": 25, "city": "Guadalajara"}
2
3# Iterate over keys
4for key in person:
5    print(key)  # name, age, city
6
7# Iterate over values
8for value in person.values():
9    print(value)  # Ana, 25, Guadalajara
10
11# Iterate over keys and values at the same time
12for key, value in person.items():
13    print(f"{key}: {value}")
14# name: Ana
15# age: 25
16# city: Guadalajara

Dictionary methods

Dictionaries have very useful methods for working with their data:

python
1person = {"name": "Ana", "age": 25, "city": "Guadalajara"}
2
3# keys() - get all keys
4print(person.keys())    # dict_keys(['name', 'age', 'city'])
5
6# values() - get all values
7print(person.values())  # dict_values(['Ana', 25, 'Guadalajara'])
8
9# items() - get key-value pairs as tuples
10print(person.items())
11# dict_items([('name', 'Ana'), ('age', 25), ('city', 'Guadalajara')])
12
13# get() - get value with a default
14phone = person.get("phone", "Not registered")
15print(phone)  # Not registered
16
17# update() - update with another dictionary
18person.update({"age": 26, "profession": "engineer"})
19print(person)
20# {'name': 'Ana', 'age': 26, 'city': 'Guadalajara', 'profession': 'engineer'}
21
22# pop() - remove and return a value
23city = person.pop("city")
24print(city)     # Guadalajara
25print(person)   # {'name': 'Ana', 'age': 26, 'profession': 'engineer'}
26
27# Check if a key exists
28print("name" in person)   # True
29print("phone" in person)  # False
💡 Tip: Always use get() instead of dictionary["key"] when you are not sure the key exists. This way you avoid KeyError exceptions.

Sets: collections without duplicates

A set is an unordered collection of unique elements. It does not allow duplicates and has no defined order. Sets are created with curly braces {} or with set().

Creating and using sets

python
1# Create a set
2fruits = {"apple", "banana", "orange", "apple"}
3print(fruits)  # {'apple', 'banana', 'orange'} (no duplicates!)
4
5# Create a set from a list (removes duplicates)
6numbers = [1, 2, 2, 3, 3, 3, 4]
7unique = set(numbers)
8print(unique)  # {1, 2, 3, 4}
9
10# Add elements
11fruits.add("grape")
12print(fruits)  # {'apple', 'banana', 'orange', 'grape'}
13
14# Remove elements
15fruits.discard("banana")  # no error if it doesn't exist
16print(fruits)  # {'apple', 'orange', 'grape'}

Set operations

Sets are especially useful for mathematical set operations:

python
1python_devs = {"Ana", "Luis", "Maria", "Carlos"}
2java_devs = {"Luis", "Pedro", "Maria", "Sofia"}
3
4# Union: all elements from both sets
5everyone = python_devs | java_devs  # or python_devs.union(java_devs)
6print(everyone)  # {'Ana', 'Luis', 'Maria', 'Carlos', 'Pedro', 'Sofia'}
7
8# Intersection: elements in both sets
9both = python_devs & java_devs  # or python_devs.intersection(java_devs)
10print(both)  # {'Luis', 'Maria'}
11
12# Difference: elements in one but not the other
13only_python = python_devs - java_devs  # or python_devs.difference(java_devs)
14print(only_python)  # {'Ana', 'Carlos'}
15
16# Symmetric difference: elements in one or the other, but not both
17exclusive = python_devs ^ java_devs
18print(exclusive)  # {'Ana', 'Carlos', 'Pedro', 'Sofia'}
📌 Note: To create an empty set use set(), not {}. Empty curly braces {} create an empty dictionary, not a set.

Comparison table of the 4 structures

This table summarizes the main differences between the 4 data structures:

Feature List [] Tuple () Dictionary {} Set {}
Mutable Yes No Yes Yes
Ordered Yes Yes Yes (since Python 3.7) No
Allows duplicates Yes Yes No (unique keys) No
Index access Yes Yes By key No
Typical use Modifiable collections Constant data Key-value mapping Unique elements
Example [1, 2, 3] (1, 2, 3) {"a": 1} {1, 2, 3}

List comprehensions: creating lists quickly

List comprehensions are an elegant and fast way to create lists in a single line. It is like a shortcut that combines a for loop with an append.

Basic syntax

python
1# Traditional way
2squares = []
3for n in range(1, 6):
4    squares.append(n ** 2)
5print(squares)  # [1, 4, 9, 16, 25]
6
7# With list comprehension (one line!)
8squares = [n ** 2 for n in range(1, 6)]
9print(squares)  # [1, 4, 9, 16, 25]

With a condition (filter)

python
1# Only even numbers
2evens = [n for n in range(1, 11) if n % 2 == 0]
3print(evens)  # [2, 4, 6, 8, 10]
4
5# Words that start with 'p'
6words = ["python", "java", "php", "rust", "perl"]
7with_p = [w for w in words if w.startswith("p")]
8print(with_p)  # ['python', 'php', 'perl']
9
10# Convert to uppercase
11uppercased = [w.upper() for w in words]
12print(uppercased)  # ['PYTHON', 'JAVA', 'PHP', 'RUST', 'PERL']
💡 Tip: List comprehensions are faster and more "Pythonic" than traditional loops. However, do not overuse them. If the logic is complex, a regular for loop is more readable.

Practical example: contact book

Let's build a contact book using dictionaries to put everything we learned into practice:

python
1# Contact book using a list of dictionaries
2contacts = []
3
4def add_contact(name, phone, email=""):
5    """Adds a new contact to the book."""
6    contact = {
7        "name": name,
8        "phone": phone,
9        "email": email
10    }
11    contacts.append(contact)
12    print(f"Contact '{name}' added successfully.")
13
14def search_contact(name):
15    """Searches for a contact by name."""
16    results = [c for c in contacts if name.lower() in c["name"].lower()]
17    if results:
18        for c in results:
19            print(f"  Name: {c['name']}")
20            print(f"  Phone: {c['phone']}")
21            print(f"  Email: {c['email'] or 'Not registered'}")
22            print("  ---")
23    else:
24        print(f"  No contacts found with '{name}'.")
25
26def show_contacts():
27    """Shows all contacts."""
28    if not contacts:
29        print("  The contact book is empty.")
30        return
31    print(f"  Total contacts: {len(contacts)}")
32    for i, c in enumerate(contacts, 1):
33        print(f"  {i}. {c['name']} - {c['phone']}")
34
35def delete_contact(name):
36    """Deletes a contact by exact name."""
37    for c in contacts:
38        if c["name"].lower() == name.lower():
39            contacts.remove(c)
40            print(f"  Contact '{name}' deleted.")
41            return
42    print(f"  Contact '{name}' not found.")
43
44# Let's test the contact book
45add_contact("Ana Lopez", "555-1234", "[email protected]")
46add_contact("Carlos Ruiz", "555-5678")
47add_contact("Ana Maria", "555-9999", "[email protected]")
48
49print("\n--- Search 'ana' ---")
50search_contact("ana")
51
52print("\n--- All contacts ---")
53show_contacts()
54
55print("\n--- Delete 'Carlos Ruiz' ---")
56delete_contact("Carlos Ruiz")
57
58print("\n--- Updated contacts ---")
59show_contacts()

This example combines lists (to store the contacts), dictionaries (to represent each contact), and list comprehensions (to search contacts). This is a very common pattern in Python.

Summary and next article

In this article we learned the 4 fundamental data structures in Python:

  • Lists: ordered and modifiable collections, ideal for most use cases
  • Tuples: like lists but immutable, perfect for data that should not change
  • Dictionaries: key-value pairs, ideal for representing objects with properties
  • Sets: collections without duplicates, useful for set operations

We also learned list comprehensions to create lists quickly and elegantly, and built a contact book as a practical example.

📌 Next article: In part 6 we will learn how to handle files — reading, writing, and organizing data in text files, CSV, and JSON. This will allow you to save data permanently so it is not lost when you close your program.
Share:
CV

Cristhian Villegas

Software Engineer specializing in Java, Spring Boot, Angular & AWS. Building scalable distributed systems with clean architecture.

Comments

Sign in to leave a comment

No comments yet. Be the first!

Related Articles