Data Structures: Lists, Dicts & Sets
Work with Python's core built-in containers: lists, tuples, dictionaries, and sets — and apply them to real security use cases.
Learning Objectives
- → Create and manipulate lists, tuples, dicts, and sets
- → Use list comprehensions for concise data transformation
- → Apply dicts to store structured data like scan results
- → Use sets for deduplication and membership testing
- → Understand mutability and when to use each structure
Lists
An ordered, mutable sequence:
open_ports = [22, 80, 443, 8080]
open_ports.append(3306)
open_ports.insert(0, 21)
open_ports.remove(8080)
print(open_ports[0]) # first item
print(open_ports[-1]) # last item
print(open_ports[1:3]) # slice [80, 443]
print(len(open_ports)) # count
Useful methods: append, extend, insert, remove, pop, sort, reverse, index, count.
List Comprehensions
ports = range(1, 1025)
high = [p for p in ports if p > 1000]
squared = [p**2 for p in [1,2,3,4]]
services = [f"port_{p}" for p in [22, 80, 443]]
Tuples
Immutable sequences — use for fixed data:
endpoint = ("192.168.1.1", 443)
host, port = endpoint # unpacking
print(endpoint[1]) # 443
Tuples are hashable, so they can be dict keys or set members.
Dictionaries
Key-value store — O(1) lookup:
scan_result = {
"host": "192.168.1.1",
"ports": [22, 80, 443],
"os": "Linux",
"is_up": True,
}
print(scan_result["host"])
scan_result["mac"] = "AA:BB:CC:DD:EE:FF" # add key
del scan_result["is_up"] # remove key
print(scan_result.get("version", "unknown")) # safe get
Iterating:
for key, value in scan_result.items():
print(f" {key}: {value}")
keys = list(scan_result.keys())
values = list(scan_result.values())
Nested dicts for multi-host results:
network = {
"192.168.1.1": {"ports": [22, 80], "os": "Linux"},
"192.168.1.2": {"ports": [3389], "os": "Windows"},
}
for ip, info in network.items():
print(ip, "→", info["ports"])
Sets
Unordered, unique elements:
seen_ips = {"10.0.0.1", "10.0.0.2", "10.0.0.1"}
print(seen_ips) # {'10.0.0.1', '10.0.0.2'} — deduped
seen_ips.add("10.0.0.3")
seen_ips.discard("10.0.0.2") # no error if missing
print("10.0.0.1" in seen_ips) # True — O(1) lookup
Set operations (great for comparing scan results):
baseline = {"22", "80", "443"}
current = {"22", "80", "8080"}
new_ports = current - baseline # {"8080"} — difference
closed_ports = baseline - current # {"443"}
common = baseline & current # {"22","80"} — intersection
all_ports = baseline | current # union
Choosing the Right Structure
| Structure | Ordered | Mutable | Unique | Use case |
|---|---|---|---|---|
| list | ✓ | ✓ | ✗ | Sequences, port lists |
| tuple | ✓ | ✗ | ✗ | Fixed records, dict keys |
| dict | ✓ (3.7+) | ✓ | keys | Lookup tables, scan results |
| set | ✗ | ✓ | ✓ | Dedup, membership tests |
Mini Project – Baseline Diff
import json
baseline = {"22", "80", "443"}
current = {"22", "80", "8080", "3306"}
new = current - baseline
gone = baseline - current
print("NEW PORTS:", new or "none")
print("CLOSED PORTS:", gone or "none")
result = {"new": list(new), "closed": list(gone)}
print(json.dumps(result, indent=2))
Create a list of 5 IP addresses. Use append(), remove(), and slicing to: add a new IP, remove the third one, and print the last two.
What method adds an element to the end of a list?
What does list[1:3] return for [10,20,30,40,50]?
Build a dict representing a scan result with keys: host, open_ports (list), os, and uptime. Iterate over .items() and print each key-value pair.
What method returns key-value pairs for iteration?
What does dict.get('key', 'default') return if 'key' is missing?
Implement the Baseline Diff mini project. Define baseline and current as sets of port strings and print new/closed ports using set operations.
What set operator finds elements in A but not in B?