Conditionals and Loops

This is the lesson where scripts start making decisions. Conditionals let your code judge each line of a config; loops let it judge every line of every config — which is the entire point of automating a network.

In this lesson you will:
  • Write if/elif/else blocks that branch on network facts
  • Combine comparisons with and, or, and not
  • Loop over lists of lines, interfaces, and devices with for
  • Build filtered lists with the accumulator pattern
  • Track line numbers with enumerate() for real config audits

Conditionals: code that judges

Everything in automation reduces to questions with yes/no answers. Is this line an interface? Is this VLAN in the voice range? Does this config contain aaa new-model? In Python, a question is an expression that evaluates to a booleanTrue or False:

>>> vlan = 150
>>> vlan >= 100
True
>>> vlan == 150        # == asks; = assigns
True
>>> "aaa new-model" in config
False

if acts on the answer, elif chains more questions, else catches everything left:

if vlan < 100:
    role = "users"
elif vlan < 200:
    role = "voice"
elif vlan < 300:
    role = "management"
else:
    role = "other"

The indented block under each branch is what runs — indentation isn’t style in Python, it is the syntax. Four spaces, consistently, never tabs. Combine conditions with and, or, and not:

if line.startswith("interface") and "Te" in line:
    print("found an uplink stanza")

One more idea that makes code read like English — truthiness. Empty things ("", [], 0) count as False; non-empty things count as True:

if matches:                  # "if we found anything"
    print(f"{len(matches)} findings")
else:
    print("clean")

Loops: code that scales

A for loop runs a block once per item in a list. That’s the whole mechanism — and it’s the difference between checking one switch and checking the district:

devices = ["den-acc-sw01", "den-acc-sw02", "den-core-sw01"]
for device in devices:
    print(f"auditing {device}...")

You choose the loop variable’s name. Choose well — for line in lines, for intf in interfaces, for device in devices read like sentences; for x in y reads like a puzzle.

The accumulator pattern — most of parsing is this

Start with an empty list, loop, keep what matches:

interfaces = []
for line in config_lines:
    if line.startswith("interface "):
        interfaces.append(line)

Four lines, and you’ve filtered a 400-line config down to its interface stanzas. Lesson 5 adds regex for fancier matching and Lesson 6 wraps this in reusable functions, but the skeleton never changes: empty list → loop → condition → append.

enumerate(): findings need line numbers

An audit finding without a line number is a scavenger hunt. enumerate(lines) yields (index, item) pairs:

for i, line in enumerate(config_lines):
    if "switchport mode trunk" in line:
        print(f"line {i + 1}: {line.strip()}")

(The i + 1 is because humans count config lines from 1, not 0.)

break and continue — loop steering

break exits the loop entirely (you found what you came for); continue skips to the next item (this one doesn’t apply):

for line in config_lines:
    if line.startswith("!"):
        continue          # comment separator — skip it
    if line == "end":
        break             # nothing meaningful after this
    process(line)
🖥 Making decisions about every line
▶ Try it yourself (Python runs in your browser)
Output appears here. First run downloads the Python runtime (~10 MB), so give it a few seconds.

Exercises (graded)

cd labs/python-foundations/lesson03
pytest -q

Five functions in exercises.py — number five is the first real audit:

  1. classify_vlan(vlan_id) — map a VLAN ID to its role by range
  2. find_interfaces(config_lines) — all lines that open an interface stanza
  3. count_matching(lines, text) — how many lines contain text
  4. access_ports(interfaces) — everything that isn’t a TenGig uplink
  5. missing_descriptions(config_lines)challenge: interface names whose next line is not a description (a real compliance check — combine enumerate, indexing, and .startswith())
✅ Check your understanding

Your script dies with SyntaxError pointing at: if hostname = "den-core-sw01": — what is wrong?

1 / 3

Summary

Conditionals turn facts into decisions: if/elif/else branch on comparisons (==, not =), joined by and/or/not, with truthiness letting if matches: read as plain English. Loops apply those decisions at scale: for line in lines visits everything, the accumulator pattern (empty list → loop → condition → append) filters configs in four lines, enumerate() attaches the line numbers an audit needs, and break/continue steer. You also learned the silent-bug rule: never modify a list mid-loop — build a new one. Next lesson: dictionaries and sets, where device inventories stop being parallel lists and start being real data structures.