Python-Data Structures for Beginners

Until now, every variable you have created holds one single value — a number, a string, a boolean. But most real programs deal with collections of things: a list of usernames, a set of IP addresses, a dictionary of settings. Python gives you four built-in data structures designed exactly for this: Lists, Tuples, Dictionaries, and Sets.


This is one of the most important lessons in the series. Once you understand these four structures, you will be able to handle virtually any kind of data in your programs.

Table of Contents

  1. Lists
  2. List Methods
  3. Tuples
  4. Dictionaries
  5. Dictionary Methods
  6. Sets
  7. Nested Data Structures
  8. How to Choose the Right Structure
  9. Practical Examples
  10. Frequently Asked Questions
  11. Conclusion

1. Lists

A list is an ordered, changeable collection that can hold any mix of data types. Lists are the most commonly used data structure in Python.

You create a list using square brackets [ ], with items separated by commas.

# A list of strings
tools = ["Nmap", "Wireshark", "Metasploit", "Burp Suite"]

# A list of numbers
ports = [21, 22, 80, 443, 8080]

# A mixed list
mixed = ["admin", 42, True, 3.14]

# An empty list
empty = []

Accessing Items — Indexing

Each item in a list has an index — a number representing its position. Python indexes start at 0, not 1.

tools = ["Nmap", "Wireshark", "Metasploit", "Burp Suite"]

print(tools[0])   # Nmap
print(tools[1])   # Wireshark
print(tools[3])   # Burp Suite
print(tools[-1])  # Burp Suite (last item)
print(tools[-2])  # Metasploit (second from last)

Slicing — Getting a Range of Items

tools = ["Nmap", "Wireshark", "Metasploit", "Burp Suite", "Hydra"]

print(tools[1:3])   # ['Wireshark', 'Metasploit'] - index 1 up to but not including 3
print(tools[:2])    # ['Nmap', 'Wireshark'] - from start up to index 2
print(tools[2:])    # ['Metasploit', 'Burp Suite', 'Hydra'] - from index 2 to end

Modifying a List

tools = ["Nmap", "Wireshark", "Metasploit"]

# Change an item
tools[1] = "Aircrack-ng"
print(tools)  # ['Nmap', 'Aircrack-ng', 'Metasploit']

# Add to the end
tools.append("Burp Suite")
print(tools)  # ['Nmap', 'Aircrack-ng', 'Metasploit', 'Burp Suite']

# Remove an item
tools.remove("Aircrack-ng")
print(tools)  # ['Nmap', 'Metasploit', 'Burp Suite']

Looping Through a List

ports = [22, 80, 443, 8080]

for port in ports:
    print(f"Checking port {port}...")

2. List Methods

Lists come with many built-in methods. Here are the most useful ones:

items = [3, 1, 4, 1, 5, 9, 2, 6]

items.append(7)       # Add 7 to the end
items.insert(0, 0)    # Insert 0 at index 0
items.remove(1)       # Remove first occurrence of 1
popped = items.pop()  # Remove and return last item
items.sort()          # Sort in ascending order
items.reverse()       # Reverse the list
items.clear()         # Remove all items

names = ["Zara", "Alice", "Bob"]
names.sort()
print(names)          # ['Alice', 'Bob', 'Zara']

print(len(names))     # 3 - number of items
print("Alice" in names)  # True - check if item exists

3. Tuples

A tuple is like a list, but it is immutable — once created, it cannot be changed. You cannot add, remove, or modify items. Tuples are used for data that should stay fixed.

You create a tuple using parentheses ( ).

# A tuple of RGB colours
red = (255, 0, 0)
green = (0, 255, 0)

# A tuple of server details that should not change
server = ("192.168.1.1", 22, "SSH")

# Accessing items - same as lists, using indexes
print(server[0])   # 192.168.1.1
print(server[2])   # SSH

# Trying to change a tuple causes an error
# server[0] = "10.0.0.1"   # TypeError: 'tuple' object does not support item assignment

When to Use a Tuple Instead of a List

  • When the data should not be changed accidentally — like coordinates, RGB values, or fixed configuration
  • Tuples are slightly faster than lists
  • Tuples can be used as dictionary keys; lists cannot

Tuple Unpacking

You can unpack a tuple's values directly into separate variables in one line:

server = ("192.168.1.1", 22, "SSH")
ip, port, protocol = server

print(ip)        # 192.168.1.1
print(port)      # 22
print(protocol)  # SSH

4. Dictionaries

A dictionary stores data as key-value pairs. Instead of accessing items by position (index), you access them by a meaningful key — like looking something up in a real dictionary using a word to find its definition.

You create a dictionary using curly braces { }, with each entry written as key: value.

# A dictionary of user information
user = {
    "username": "thecrazyhacker",
    "email": "admin@verxio.site",
    "role": "admin",
    "active": True
}

# Accessing values by key
print(user["username"])   # thecrazyhacker
print(user["role"])       # admin
print(user["active"])     # True

Adding and Modifying Items

user = {"username": "thecrazyhacker", "role": "admin"}

# Add a new key-value pair
user["email"] = "admin@verxio.site"

# Modify an existing value
user["role"] = "superadmin"

print(user)
# {'username': 'thecrazyhacker', 'role': 'superadmin', 'email': 'admin@verxio.site'}

Removing Items

user = {"username": "thecrazyhacker", "role": "admin", "temp_key": "delete_me"}

del user["temp_key"]           # Delete by key
removed = user.pop("role")     # Remove and return value
print(removed)                  # admin
print(user)                     # {'username': 'thecrazyhacker'}

Checking if a Key Exists

user = {"username": "thecrazyhacker", "email": "admin@verxio.site"}

if "email" in user:
    print(f"Email is: {user['email']}")

if "password" not in user:
    print("No password stored")

Looping Through a Dictionary

config = {
    "host": "localhost",
    "port": 3306,
    "database": "verxio_db",
    "user": "root"
}

# Loop through keys
for key in config:
    print(key)

# Loop through values
for value in config.values():
    print(value)

# Loop through both key and value
for key, value in config.items():
    print(f"{key}: {value}")

5. Dictionary Methods

config = {"host": "localhost", "port": 3306}

# Get a value safely (returns None if key doesn't exist instead of an error)
print(config.get("host"))       # localhost
print(config.get("password"))   # None
print(config.get("password", "not set"))  # not set (default value)

# Get all keys
print(config.keys())    # dict_keys(['host', 'port'])

# Get all values
print(config.values())  # dict_values(['localhost', 3306])

# Get all key-value pairs as tuples
print(config.items())   # dict_items([('host', 'localhost'), ('port', 3306)])

# Merge another dictionary in
extra = {"ssl": True, "timeout": 30}
config.update(extra)
print(config)
# {'host': 'localhost', 'port': 3306, 'ssl': True, 'timeout': 30}

6. Sets

A set is an unordered collection of unique values. Sets automatically remove duplicates, and they do not maintain any particular order. They are extremely fast for checking whether something exists in the collection.

You create a set using curly braces { } — but unlike dictionaries, there are no key-value pairs, just values.

# Creating a set
open_ports = {22, 80, 443, 8080, 22, 80}   # duplicates are removed automatically
print(open_ports)   # {8080, 443, 22, 80} - order is not guaranteed

# Creating a set from a list (useful for removing duplicates)
ip_list = ["10.0.0.1", "10.0.0.2", "10.0.0.1", "10.0.0.3", "10.0.0.2"]
unique_ips = set(ip_list)
print(unique_ips)   # {'10.0.0.3', '10.0.0.1', '10.0.0.2'}

Adding and Removing from Sets

ports = {22, 80, 443}

ports.add(8080)        # Add a single item
ports.discard(22)      # Remove if exists (no error if not found)
ports.remove(80)       # Remove (raises error if not found)

print(ports)   # {443, 8080}

Set Operations — The Real Power of Sets

group_a = {1, 2, 3, 4, 5}
group_b = {4, 5, 6, 7, 8}

# Union - all items from both sets
print(group_a | group_b)        # {1, 2, 3, 4, 5, 6, 7, 8}

# Intersection - only items in BOTH sets
print(group_a & group_b)        # {4, 5}

# Difference - items in A but not in B
print(group_a - group_b)        # {1, 2, 3}

# Symmetric difference - items in either set but not both
print(group_a ^ group_b)        # {1, 2, 3, 6, 7, 8}

7. Nested Data Structures

Data structures can be nested inside each other. A list can contain dictionaries. A dictionary can have lists as values. This is how complex real-world data is represented.

# A list of dictionaries - a common pattern for storing records
users = [
    {"username": "alice", "role": "admin", "active": True},
    {"username": "bob", "role": "editor", "active": False},
    {"username": "charlie", "role": "viewer", "active": True}
]

# Access the second user's username
print(users[1]["username"])   # bob

# Loop through all users and print active ones
for user in users:
    if user["active"]:
        print(f"{user['username']} ({user['role']}) is active")

Output:

alice (admin) is active
charlie (viewer) is active
# A dictionary with lists as values
network_scan = {
    "open_ports": [22, 80, 443],
    "os_guess": ["Linux", "Ubuntu 22.04"],
    "services": ["SSH", "HTTP", "HTTPS"]
}

print(network_scan["open_ports"])       # [22, 80, 443]
print(network_scan["services"][0])      # SSH

8. How to Choose the Right Structure

StructureUse WhenExample
ListOrdered collection that may changeA list of scan results
TupleOrdered collection that should not changeCoordinates (x, y), server config
DictionaryKey-value pairs, lookup by nameUser profile, config settings
SetUnique values, fast membership checksUnique IPs, visited URLs

9. Practical Examples

Contact Book Using a Dictionary

contacts = {}

def add_contact(name, phone, email):
    contacts[name] = {"phone": phone, "email": email}

def lookup(name):
    if name in contacts:
        info = contacts[name]
        print(f"Name:  {name}")
        print(f"Phone: {info['phone']}")
        print(f"Email: {info['email']}")
    else:
        print(f"{name} not found.")

add_contact("Alice", "+254700000001", "alice@email.com")
add_contact("Bob", "+254700000002", "bob@email.com")

lookup("Alice")
lookup("Charlie")

Remove Duplicate IPs from a Scan List

raw_scan = [
    "192.168.1.1",
    "192.168.1.5",
    "192.168.1.1",
    "10.0.0.1",
    "192.168.1.5",
    "10.0.0.2"
]

unique = list(set(raw_scan))
unique.sort()

print(f"Found {len(raw_scan)} results, {len(unique)} unique:")
for ip in unique:
    print(f"  {ip}")

10. Frequently Asked Questions

What is the difference between a list and a tuple?

Both are ordered sequences that can hold any data. The key difference is that lists are mutable (changeable) and tuples are immutable (fixed). Use a list when the data might change. Use a tuple when it should stay constant.

What is the difference between a dictionary and a list?

A list stores items you access by their position (index 0, 1, 2...). A dictionary stores items you access by a meaningful name (key). Use a list for ordered sequences. Use a dictionary when each item has a label or name.

Can a dictionary have duplicate keys?

No. Every key in a dictionary must be unique. If you assign a value to a key that already exists, the old value is overwritten. Dictionary values, however, can be duplicated.

Why is my set printing in a different order every time?

Sets are unordered by design. Python does not guarantee any particular order for set items. If you need an ordered unique collection, convert the set to a sorted list: sorted(my_set).

Can I put a list inside another list?

Yes. This is called a nested list and is used to represent things like grids or tables. You access items with double indexing: grid[row][column].


Conclusion

Lists, tuples, dictionaries, and sets are the four pillars of data handling in Python. Every real project uses them constantly — storing records, looking up values, removing duplicates, processing collections. The more comfortable you are with these structures, the faster you will be able to build things.

Practice by experimenting: create each structure, add and remove items, loop through them, and nest them together. That hands-on experience will make these concepts permanent.

In the next part of the Python series we cover String Methods — everything Python can do with text, from slicing and searching to formatting and replacing. Strings are everywhere in programming and Python has some of the most powerful string tools of any language.

Popular Posts