DEV Community

Maureen Kipkosgei
Maureen Kipkosgei

Posted on

The Right Container for the Job: Python Data Structures

Data structures is a format that is used for organizing, managing, and storing data in computer's memory so that it can be accessed and modified efficiently. Data structures act as containers that hold multiple values at once. Choosing the right data structure affects how fast your program runs, how much memory it uses, and how readable the code is.

Python has four highly optimized built-in data structures: lists, dictionaries, tuples and sets.

List([])

A list is an ordered collection that can hold items of any type, and it can grow, shrink, or be modified after creation. It is mainly used to store items where order matters, and you expect to add, remove or change items over time.

Example of a list

shopping_list = ['Bread','Sugar','Rice','Milk']
print(shopping_list) # ['Bread','Sugar','Rice','Milk']
Enter fullscreen mode Exit fullscreen mode

Indexing a List

A list can be accessed using an index which is its position number. List indexing is zero-based, meaning the first item on the list is at index 0, then second item is at index 1. Python also supports negative indexing to count backward from the end of the list.

shopping_list = ['Bread','Sugar','Rice','Milk']
# pos indexing      0       1       2      3
# neg indexing      -4      -3      -2     -1
Enter fullscreen mode Exit fullscreen mode

Positive indexing
Starts at 0 from the left side

shopping_list = ['Bread','Sugar','Rice','Milk']
print(shopping_list[0]) # 'Bread' (first item)
print(shopping_list[1]) # 'Sugar' (second item)
Enter fullscreen mode Exit fullscreen mode

Negative indexing
Starts at -1 from the right side. This is perfect when you want the item but you do not know how long the list is.

shopping_list = ['Bread','Sugar','Rice','Milk']
print(shopping_list[-1]) # 'Milk' (last item)
print(shopping_list[-2]) # 'Rice' ( second-last-item)
Enter fullscreen mode Exit fullscreen mode

Changing an item by index

shopping_list = ['Bread','Sugar','Rice','Milk']
shopping_list[3] = 'Fresh Milk'
shopping_list[1] = 'Honey'
print(shopping_list) # ['Bread','Honey','Rice','Fresh Milk']
Enter fullscreen mode Exit fullscreen mode

Slicing a list

List slicing is the technique used to extract a subset of a list instead of just a single item. Slicing uses the syntax list[start:stop:step].It creates a brand new list without altering the original list.

Slicing parameters

  • start - the index where the slice begins(this item is included)

  • stop - the index where the slice ends( this item is not included)

  • step - this is optional it determines the increment, i.e a step of 2 skips every other item.

  • There are some shortcuts used, if you leave a parameter blank, Python assumes you mean the very beginning or the end.

Example of slicing

numbers = [10, 20, 30, 40, 50, 60, 70, 80, 90]
#           0   1  2   3   4   5   6   7   8

print(numbers[1:4]) # [20, 30, 40]
print(numbers[:3])  # [10, 20, 30]
print(numbers[4:]) # [50, 60, 70, 80, 90]

print(numbers[::2])    #every 2nd item [10, 30, 50, 70, 90]
print(numbers[::-1]) # from the last item to the first
Enter fullscreen mode Exit fullscreen mode

List Methods

List methods are built-in functions that allow one to manipulate, modify, or search lists directly.
Let's assume we start with an initial list :
students = ['Amos','Faith','Wanjiku','Brian','Kevin']

Adding Items

  • .append(item) - adds a single item to the end of the list.
students.append('Dennis')              
print(students) # ['Amos','Faith','Wanjiku','Brian','Kevin','Dennis']

Enter fullscreen mode Exit fullscreen mode
  • .extend(items) - used to add multiple items or append all items from another list.
students.extend(['Peter','Mercy'])     
print(students)# ['Amos','Faith','Wanjiku','Brian','Kevin','Dennis','Peter','Mercy']
Enter fullscreen mode Exit fullscreen mode
  • insert(index,item) - inserts an item at a specific position, shifting everything to the right.
students.insert(1, 'Grace')
print(students) # ['Amos','Grace','Faith','Wanjiku','Brian','Kevin','Dennis','Peter','Mercy'] 
Enter fullscreen mode Exit fullscreen mode

Removing Items

  • .pop(index) - removes and returns the item at the given index. if no index is provided, it removes the very last item.
print(students.pop(0)) # removes and returns 'Amos'
print(students.pop()) # removes and returns 'Mercy'
Enter fullscreen mode Exit fullscreen mode
  • .remove(item) - searches the first occurrence of a specific value and deletes it. Throws a ValueError if the value is not there.
students.remove('Brian')
print(students) # removes 'Brian' from the list
Enter fullscreen mode Exit fullscreen mode
  • del - this is a python keyword that deletes an item by its index position. Del can delete multiple items using slices and it raises an IndexError if the index does not exist.
del students[:3]
print(students) # removes from start up to position 3 'Grace', 'Faith', 'Wanjiku
Enter fullscreen mode Exit fullscreen mode
  • .clear() - removes all items leaving the list empty.
students.clear()
print(students) # []
Enter fullscreen mode Exit fullscreen mode

Ordering a list

  • .sort - sorts items of the list in place(ascending by default, alphabetically for strings, ascending for numbers). Set reverse=True to sort descending.
numbers = [3,1,7,4,9,5]
numbers.sort()
print(numbers) # [1,3,4,5,7,9]
Enter fullscreen mode Exit fullscreen mode
numbers = [3,1,7,4,9,5]
numbers.sort(reverse=True)
print(numbers) # [9,7,5,4,3,1]
Enter fullscreen mode Exit fullscreen mode

The list can also be sorted by the length of the characters in strings.

students = ['Amos','Wanjiku','Faith','Dennis']
students.sort(key=len)
print(students) # ['Amos','Faith','Dennis','Wanjiku']
Enter fullscreen mode Exit fullscreen mode
  • .reverse() - reverses the order of items in the list in place.
numbers.reverse()
print(numbers) # [5,9,4,7,1,3]
Enter fullscreen mode Exit fullscreen mode
  • .copy() - returns a backup copy of the list incase you remove the wrong item, there is another list.
numbers_backup = numbers.copy() # creates a shallow copy.
Enter fullscreen mode Exit fullscreen mode

Tuples (())

A tuple looks like a list but is immutable meaning once created it cannot be modified. This makes tuples slightly faster than lists and safer to use when you want to guarantee the data won't change.
Tuples is used for fixed collections of related values, like coordinates, RGB colors, or function return values.

Example of a tuple

student = ('Njeri',19,'Kisumu')
name,age,city = student # unpacking the tuple

print(f"{name} is {age} years old, from {city}") # Njeri is 19 years old, from Kisumu
Enter fullscreen mode Exit fullscreen mode

Accessing & Slicing Tuples

Tuples supports indexing and slicing.

print(student[0]) # 'Njeri' indexing
print(student[:1]) # ('Njeri', 19) slicing
Enter fullscreen mode Exit fullscreen mode

Immutability - tuples cannot change

students[1] = 25 # CRASH! tuples can't be modified.
Enter fullscreen mode Exit fullscreen mode

Dictionaries ({key: value})

A dictionary stores data as key-value pairs, giving instant lookups by key. It is used to store structured database records, caching and JSON data handling. Use dictionary when you need to look things up by a meaningful key rather than the numeric position like mapping usernames to profiles.

Example of a dictionary

contacts = {'Amina': '0712345678','Bob':'0798765432','Faith': '0799404040'}
Enter fullscreen mode Exit fullscreen mode

Accessing Data

Use square brackets [] to enclose the key that needs to be fetched.

print(contacts['Amina']) # 0712345678
Enter fullscreen mode Exit fullscreen mode

Use .get() to fetch if you are not sure the key exists. It will return None if the key is missing.

print(contacts.get('Brian')) # None
print(contacts.get('Bob')) # 0798765432
Enter fullscreen mode Exit fullscreen mode

Adding & Updating Data

contacts['Njeri'] = '0700111122'   # adds a new key
contacts['Amina'] = '0711000000'   # updates an existing key
Enter fullscreen mode Exit fullscreen mode

Removing Data

  • del dict[key] - deletes the key-value pair entirely.
del contacts['Amina'] # removes 'Amina': '0711000000'
Enter fullscreen mode Exit fullscreen mode
  • .pop(key) - removes the key and returns its value.
contacts.pop('Faith') #removes 'Faith' and returns '0799404040'
Enter fullscreen mode Exit fullscreen mode
  • .clear() - empties the entire dictionary.
contacts.clear() # {}
Enter fullscreen mode Exit fullscreen mode

Looping through Dictionaries

Dictionaries can be iterated through keys, values, or both at the same time.

prices = {'Sugar': 150, 'Rice': 180, 'Milk': 65, 'Bread': 120}
Enter fullscreen mode Exit fullscreen mode
# loop through the keys only
for key in prices:
    print(key) 

# loop through the values only
for value in prices.value():
    print(value) 

# loop through both keys and values using .items()
for key, value in prices.items():
    print(f"{key} is {value}")
Enter fullscreen mode Exit fullscreen mode

Dictionary Methods

  • keys() - returns a list-like view of all keys.
prices.keys() #['Sugar','Rice','Milk','Bread']
Enter fullscreen mode Exit fullscreen mode
  • .values() - returns a list-like view of all values.
prices.values() # [150,180,65,120]
Enter fullscreen mode Exit fullscreen mode
  • .items() - returns a view of all key-value tuples.
prices.items() # [('Sugar',150), ('Rice',180),('Milk', 65), ('Bread',120)]
Enter fullscreen mode Exit fullscreen mode

Sets ({})

A set stores unique, unordered items. Duplicates are automatically discarded, and sets are optimized for fast membership tests. Sets support mathematical operations, which is useful for comparing collections.

# creating an empty set
empty_set = set()

routes = {'Route 46','Route 34','Route 46','Route 11','Route 11'}
print(routes) # {'Route 34','Route 46','Route 11'} # remove duplicates
Enter fullscreen mode Exit fullscreen mode

Modifying a Set

  • .add(item) - adds a single item.

  • .remove(item) - removes a specific item. Crashes with a KeyError if the item is missing.

  • .discard(item) - safely removes an item. If the item does not exist, it does not crash.

routes = {'Route 46','Route 34'}

routes.add('Route 11') # {'Route 46','Route 34','Route 11'}

routes.remove('Route 34') # {'Route 46','Route 11'}

route.add('Route 46') # does nothing , 'Route 46' already exists.

route.discard('Route 55') # does nothing because 'Route 55' does not exist (it does not crash)

'Route 46' in routes # True - fast lookup in sets.
Enter fullscreen mode Exit fullscreen mode

Mathematical Operations

Sets in python are optimized for mathematical set operations, which are useful in programming.

a = {1, 2, 3}
b = {2, 3, 4}

# union(|) - combines elements from both sides
print(a | b) # {1,2,3,4}

# intersection(&) - finds items present in both sets
print(a & b) # {2,3}

# difference(-) - finds items in `a` that are not in `b`
print(a - b) # {1}

# symmetric difference(^) - finds items that are in one of the sets not both
print(a ^ b) # {1,4}
Enter fullscreen mode Exit fullscreen mode

Quick Comparison

Structure Ordered Mutable Duplicates Access by
List Yes Yes Allowed Index
Tuple Yes No Allowed Index
Dictionary No Yes Unique Keys Key
Set No Yes Not Allowed Membership




Comprehensions

Comprehensions in Python are a concise, elegant way to create new collections (lists, dictionaries, or sets) from existing iterables in a single line of code. they are not a separate data structures, they are just fast, readable way to build the ones above.

Syntax:[expression for item in iterable if condition]

squares = [n  2 for n in range(6)]
# [0, 1, 4, 9, 16, 25]

# adding if filter
evens_only = [n for n in range(10) if n % 2 == 0]
# [0, 2, 4, 6, 8]

square_map = {n: n 2 for n in range(5)}
# {0: 0, 1: 1, 2: 4, 3: 9, 4: 16}

# dictionaries
unique_lengths = {len(word) for word in ["hi", "hey", "hello", "yo"]}
# {2, 3, 5}
Enter fullscreen mode Exit fullscreen mode




Conclusion

Most Python programs are lists, tuples, dictionaries and sets working together, understanding strengths of each one is often valuable than knowing advanced syntax. As a general rule: reach for a list when order and flexibility matter, a tuple when the data shouldn't change, a dictionary when you need fast lookups by a meaningful key, and a set when uniqueness or fast membership checks matter most. Getting this choice right early on tends to make the rest of your code simpler.

Top comments (0)