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.
Exercises (graded)
cd labs/python-foundations/lesson02
pytest -q
Five functions in exercises.py:
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
Reference solutions in solutions/ - after an honest attempt.
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.