Numbers: subnet math without a calculator tab
Python has two numeric types you’ll use constantly: integers (int) for
things you count - ports, VLANs, prefix lengths - and floats (float)
for things you measure - utilization, error rates. The operators are mostly
what you’d expect, plus three that matter more in networking than anywhere
else:
>>> 2 ** (32 - 24) - 2 # ** is exponent: usable hosts in a /24
254
>>> 48 // 12 # // is integer division (no remainder)
4
>>> 530 % 48 # % is modulo: the remainder
2
That first line is the one to tattoo somewhere: a /26 has
2 ** (32 - 26) - 2 = 62 usable addresses, and now you never count on your
fingers during a design review again. (That is the traditional formula for
normal IPv4 LAN subnets; /31 point-to-points and /32 host routes are
special cases, and Lesson 9 shows the production-safe library version.)
Division with / always returns a
float, which pairs with round() for human-readable reporting:
>>> used, total = 87, 254
>>> round(used / total * 100, 1)
34.3
Files: configs live on disk, not in single lines
Lesson 1 parsed one line at a time. Real work starts with whole files -
saved configs, inventory exports, show output you redirected last night.
The professional pattern is the with statement:
with open("acc-sw03.cfg") as f:
config = f.read()
lines = config.splitlines()
with guarantees the file gets closed when the block ends - including when
your code crashes halfway through. The bare f = open(...) form you’ll see
in old scripts leaks file handles when things go wrong; just don’t.
View diagram source - it's just text (Mermaid). Diagrams-as-code is how modern network docs work; the flagship course has a free module on it.
flowchart LR
A[/"acc-sw03.cfg<br/>(on disk)"/] -- "with open(...)" --> B["file object f"]
B -- ".read()" --> C["one big string"]
C -- ".splitlines()" --> D["['hostname acc-sw03',<br/>'vlan 10', ..., 'end']"]
D -- "lines[-1]" --> E["'end'"]Two reading styles cover nearly everything:
f.read()- the whole file as one string. Pair with.splitlines()to get a clean list of lines with no trailing\ncharacters.f.readlines()- a list of lines with their newlines still attached. Usually the wrong choice for exactly that reason.
Writing is the same shape with a mode argument:
with open("pre-check-acc-sw03.txt", "w") as f:
f.write(version_output)
Lists: the container you’ll use every single day
A list is an ordered, changeable collection - and almost everything in network automation arrives as one: lines of a config, interfaces on a switch, devices in a site.
>>> uplinks = ["Gi1/0/1", "Gi1/0/2", "Te1/1/1", "Te1/1/2"]
>>> len(uplinks)
4
>>> uplinks[0] # indexing starts at ZERO
'Gi1/0/1'
>>> uplinks[-1] # negatives count from the end
'Te1/1/2'
Slicing pulls out sub-lists with [start:stop] - start included, stop
excluded:
>>> uplinks[0:2]
['Gi1/0/1', 'Gi1/0/2']
>>> uplinks[-2:] # everything from the second-to-last on: the tens
['Te1/1/1', 'Te1/1/2']
Omitting an endpoint means “from the beginning” or “to the end” - so
lines[:10] is the first ten lines of a config and lines[-5:] is the last
five. Lists grow and reorganize in place:
>>> vlans = [10, 30, 20]
>>> vlans.append(40) # add one item to the end
>>> vlans
[10, 30, 20, 40]
>>> sorted(vlans) # returns a NEW sorted list
[10, 20, 30, 40]
>>> vlans # the original is untouched
[10, 30, 20, 40]
And because a config is just a list of strings once you .splitlines() it,
everything from Lesson 1 composes with everything above:
Output appears here. First run downloads the Python runtime (~10 MB), so give it a few seconds.
Prove it (graded lab)
Write each function in the editor, then Run grader - it runs the lesson’s
real checks right here in your browser, nothing to install. Green means the
skill is yours, and these are the building blocks the Lesson 10 capstone
(netaudit) is assembled from.
Five functions:
usable_hosts(prefix_len)- usable host count for a prefix lengthutilization_pct(used, total)- percentage utilization, one decimal placeread_config_lines(path)- a file’s lines as a clean list (no newlines)get_uplinks(interfaces)- the last two interfaces in a listadd_vlan(vlans, vlan_id)- a new sorted list with the VLAN added
Reveal a reference solution
"""Lesson 2 reference solutions. Read after an honest attempt."""
def usable_hosts(prefix_len):
return 2 ** (32 - prefix_len) - 2
def utilization_pct(used, total):
return round(used / total * 100, 1)
def read_config_lines(path):
with open(path) as f:
return f.read().splitlines()
def get_uplinks(interfaces):
return interfaces[-2:]
def add_vlan(vlans, vlan_id):
return sorted(vlans + [vlan_id])
Read it, close it, then re-type your own version from memory. Wrong turns are where the learning is.
A /26 subnet - how many usable host addresses, and which expression computes it?
lines = config.splitlines() gives a 412-line config. What is lines[-2:]?
After vlans = [30, 10, 20] and vlans = vlans.sort(), what is vlans?
Summary
Integer math (**, //, %) handles subnet sizing - 2 ** (32 - prefix) - 2
- and floats with
round()handle utilization reporting, but only after youint()whatever you parsed, because parsed text is always strings. Thewith open(...)statement is the only file-reading pattern worth learning, and.read().splitlines()hands you a config as a clean list. Lists index from zero, slice with[start:stop], grow with.append(), and hide one classic trap: in-place methods like.sort()returnNone. Next lesson: conditionals and loops - where your scripts finally start making decisions about every line in that config, not just the ones you point at.