Python Lists
List creation, slicing, comprehensions, and common operations.
Creating and Modifying Lists
List literal and constructor — most common ways to create lists
interfaces = ["Gi1/0/1", "Gi1/0/2", "Gi1/0/3"]
from_range = list(range(1, 49)) # [1, 2, ..., 48]
empty = []
append vs extend — append adds one item, extend adds each item from an iterable
vlans = [10, 20]
vlans.append(30) # [10, 20, 30]
vlans.extend([40, 50]) # [10, 20, 30, 40, 50]
vlans += [60] # same as extend -- [10, 20, 30, 40, 50, 60]
insert, remove, pop — positional insertion, value removal, index removal with return
ports = [22, 80, 443]
ports.insert(0, 21) # [21, 22, 80, 443] -- insert at index 0
ports.remove(80) # [21, 22, 443] -- removes first occurrence, raises ValueError if missing
last = ports.pop() # 443 -- removes and returns last item
first = ports.pop(0) # 21 -- removes and returns item at index 0
Slicing
Basic slicing — start:stop:step, stop is exclusive
hosts = ["sw1", "sw2", "sw3", "rtr1", "rtr2"]
hosts[1:3] # ["sw2", "sw3"] -- index 1 up to (not including) 3
hosts[:2] # ["sw1", "sw2"] -- first 2
hosts[2:] # ["sw3", "rtr1", "rtr2"] -- from index 2 onward
Advanced slicing — step, reverse, negative indexing
nums = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
nums[::2] # [0, 2, 4, 6, 8] -- every 2nd element
nums[1::2] # [1, 3, 5, 7, 9] -- odd-indexed elements
nums[::-1] # [9, 8, 7, ..., 0] -- reversed
nums[-3:] # [7, 8, 9] -- last 3
Slice assignment — replace a section of a list in place
config_lines = ["hostname sw1", "!", "interface Gi1/0/1", "!"]
config_lines[2:3] = ["interface Gi1/0/1", " switchport mode access", " switchport access vlan 10"]
Comprehensions
List comprehension — builds a new list by transforming each element
upper_hosts = [h.upper() for h in hostnames]
Comprehension with filter — only include elements that pass the condition
active = [d for d in devices if d["status"] == "active"]
Comprehension with conditional expression — transform based on a condition
labels = ["UP" if port["up"] else "DOWN" for port in ports]
Nested comprehension — flatten a list of lists
all_interfaces = [intf for switch in switches for intf in switch.interfaces]
# reads as: for each switch, for each interface in that switch, collect it
Sorting
sort() vs sorted() — sort() mutates in place, sorted() returns new list
vlans = [30, 10, 50, 20]
vlans.sort() # vlans is now [10, 20, 30, 50]
ordered = sorted(vlans, reverse=True) # new list [50, 30, 20, 10], vlans unchanged
Sort by key — custom sort criteria using key function
devices = [{"name": "sw2", "ip": "10.50.1.3"}, {"name": "sw1", "ip": "10.50.1.2"}]
devices.sort(key=lambda d: d["name"]) # sort by hostname
# Multi-key sort: severity first, then timestamp
alerts.sort(key=lambda a: (a["severity"], a["timestamp"]))
Natural sort for interface names — extract the numeric part for proper ordering
interfaces = ["Gi1/0/10", "Gi1/0/2", "Gi1/0/1", "Gi1/0/24"]
interfaces.sort(key=lambda i: int(i.split("/")[-1]))
# ["Gi1/0/1", "Gi1/0/2", "Gi1/0/10", "Gi1/0/24"]
Iteration Patterns
enumerate — get index and value, start parameter offsets the counter
for i, line in enumerate(config_lines, start=1):
print(f"{i:4d}: {line}")
zip — iterate multiple lists in parallel, stops at shortest
for host, ip in zip(hostnames, ip_addresses):
print(f"{host} -> {ip}")
# strict=True (Python 3.10+) raises ValueError if lengths differ
for host, ip in zip(hostnames, ip_addresses, strict=True):
...
map and filter — functional alternatives to comprehensions
# map applies a function to every element
ips = list(map(str.strip, raw_lines))
# filter keeps elements where function returns True
reachable = list(filter(lambda h: ping(h), hosts))
# comprehension equivalents (usually preferred)
ips = [line.strip() for line in raw_lines]
reachable = [h for h in hosts if ping(h)]
Unpacking
Star unpacking — capture first, rest, or split head/tail
first, *rest = ["10.50.1.1", "10.50.1.2", "10.50.1.3"]
# first = "10.50.1.1", rest = ["10.50.1.2", "10.50.1.3"]
first, *middle, last = range(10)
# first = 0, middle = [1..8], last = 9
Unpack into function call — spread a list as positional arguments
coords = [10, 20, 30]
point = Point(*coords) # same as Point(10, 20, 30)
Nested Lists
List of lists — matrix-style data, access with double indexing
interface_table = [
["Gi1/0/1", "10.50.1.1", "up"],
["Gi1/0/2", "10.50.1.2", "down"],
["Gi1/0/3", "10.50.1.3", "up"],
]
interface_table[0][2] # "up" -- row 0, column 2
Flatten nested list — single-depth flattening with comprehension or itertools
nested = [[1, 2], [3, 4], [5, 6]]
flat = [x for sublist in nested for x in sublist]
# [1, 2, 3, 4, 5, 6]
# Or with itertools for arbitrary depth
from itertools import chain
flat = list(chain.from_iterable(nested))
Useful Patterns
Deduplicate while preserving order — dict.fromkeys trick
seen_order = list(dict.fromkeys(hostnames))
# removes duplicates, keeps first occurrence order
Chunk a list into groups of n — useful for batch processing
def chunked(lst, n):
for i in range(0, len(lst), n):
yield lst[i:i + n]
for batch in chunked(all_devices, 10):
process_batch(batch)
Check if any/all elements match — short-circuits on first result
all_up = all(d["status"] == "up" for d in devices)
any_critical = any(a["severity"] == "critical" for a in alerts)