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)