You already speak one strict, indentation‑sensitive language: IOS. The hierarchical config you write under interface GigabitEthernet0/1 only makes sense because of how it’s nested. Python is the same idea — except instead of pressing Tab for visual clarity, the indentation is the syntax. Today we cover the handful of rules that account for nine out of ten beginner mistakes, and you’ll come out the other side able to read other people’s scripts without panic.
This is Day 2 of the 21‑post Python for Network Engineers series. If you missed yesterday, go install Python 3.11+ in a virtualenv first — every example below assumes you can run python at a prompt and get the >>> REPL.
Variables: no var, no type, no semicolon
You assign with =. That’s it. There is no declaration keyword (var, let, my) and you do not declare a type up front.
hostname = "core-sw01"
mgmt_ip = "10.0.0.1"
uptime_days = 47
is_reachable = True
Names are case‑sensitive — hostname and Hostname are different variables. The convention is snake_case for variables and functions, CONSTANT_CASE for things you never reassign, and CamelCase for class names (we will get to classes much later, you don’t need them yet).
Python infers the type from the value, but each variable does have a type at any given moment. Ask with type():
>>> type(hostname)
<class 'str'>
>>> type(uptime_days)
<class 'int'>
>>> type(is_reachable)
<class 'bool'>
The five primitive types you will use every day
| Type | Example | What it represents |
|---|---|---|
int |
1500 |
Whole numbers — MTU, port numbers, AS numbers |
float |
0.5 |
Decimals — interface load, latency in ms |
str |
"GigabitEthernet0/1" |
Text — hostnames, interface names, IPs (as text) |
bool |
True |
True or False, capitalized — link up/down, reachable/not |
NoneType |
None |
“No value” — closer to IOS’s “not configured” than to 0 or "" |
Cisco context: None trips up people who come from C or Go, where you’d use 0 or an empty string as a sentinel. In Python, “this OSPF cost has not been set” is None, not 0 — because 0 is a perfectly valid OSPF cost.
Strings — single, double, triple, f‑string
Single and double quotes are interchangeable. Pick one and be consistent — most projects pick double:
banner = "Authorized access only"
warning = 'Do not use single quotes if your string contains "double quotes"'
Triple quotes preserve newlines — perfect for multi‑line config snippets:
snippet = """interface GigabitEthernet0/1
description Uplink to core
ip address 10.0.0.1 255.255.255.0
no shutdown
"""
And the most useful string form for network work — the f‑string, prefix f, anything in {} is evaluated:
vlan = 100
desc = "Voice"
print(f"vlan {vlan}\n name {desc}")
# vlan 100
# name Voice
You will use f‑strings constantly — for building config, for log lines, for messages. We dedicate all of Day 3 to them.
Indentation IS the syntax
This is the rule that surprises everyone coming from C, Java, or Perl: there are no { } braces and no end keyword. A block is defined purely by indentation.
if uptime_days > 30:
print("This box has been up a while")
print("Consider a maintenance reload")
print("This always runs")
The two indented lines belong to the if. The third line, at the same level as if, does not. The convention is 4 spaces per level — never tabs, never mixed. Configure your editor to insert 4 spaces when you press Tab. If you mix tabs and spaces, Python will throw IndentationError: unexpected indent and you will spend an hour wondering why.
The colon : at the end of if, for, while, def, and class is required. It tells Python “an indented block follows.” Forgetting it produces SyntaxError: expected ':' — which is one of the friendlier error messages you’ll see this week.
Comments and docstrings
# Single-line comment — anything after # to end of line.
mtu = 9000 # inline comment, also fine
"""Triple-quoted string used as a module or function docstring.
Python treats this as documentation, not just a comment, and tools
like help() pick it up automatically."""
Same rule as in IOS: comments should explain the why, not the what. # set MTU to 9000 tells me nothing the next line doesn’t already. # jumbo frames required by storage VLAN per ticket NET-447 earns its keep.
Operators that behave differently than you’d expect
=assigns.==compares. Confusing them is the single most common bug in week one./always returns a float, even if the math is exact:10 / 2 == 5.0. Use//for integer division.and/or/notare the boolean operators — written as words, not&&/||/!.+on strings concatenates:"Gig" + "0/1" == "Gig0/1". It does not work on a string and a number — you’ll get aTypeError.
link_speed_mbps = 1000
print("Speed: " + str(link_speed_mbps) + " Mbps") # works, but ugly
print(f"Speed: {link_speed_mbps} Mbps") # better
Truthiness — what counts as “true enough”
Python evaluates more than just True as truthy in an if. Falsy values are: False, None, 0, 0.0, "" (empty string), [] (empty list), {} (empty dict). Everything else is truthy.
interfaces = []
if interfaces:
print("Found interfaces")
else:
print("No interfaces yet") # this branch runs
This is why Python code rarely says if len(x) > 0: — it just says if x: and lets the empty container be falsy.
Reading errors instead of fearing them
Python’s tracebacks look intimidating, but they read bottom‑up. The last line is always the actual error, and the line above tells you the file and line number it happened on. Get into the habit of reading them in that order — type, then location, then everything else.
Traceback (most recent call last):
File "switch_check.py", line 4, in <module>
print("Speed: " + speed_mbps + " Mbps")
TypeError: can only concatenate str (not "int") to str
Three lines tell you: it’s a TypeError (added a string to an int), at line 4 of switch_check.py, in the print(...) call. Fix the line, re‑run.
Putting it together: a tiny script
Save this as day2.py and run python day2.py:
hostname = "edge-rtr01"
uptime_days = 142
is_reachable = True
if is_reachable and uptime_days > 90:
print(f"{hostname} has been up for {uptime_days} days — overdue for a reload window")
elif is_reachable:
print(f"{hostname} reachable, uptime healthy")
else:
print(f"{hostname} not reachable — check console")
Read it top to bottom. Notice: no semicolons, no braces, the colon at the end of each if/elif/else, the four‑space indentation, and the f‑string interpolating two variables into one message. Every Python script you’ll write this series uses these same shapes.
Exercises
- In the REPL, create a variable
mtuset to1500, then print the message"MTU is 1500 bytes"using an f‑string. - What does
type(10 / 5)print, and why? What abouttype(10 // 5)? - Predict what this prints before running it:
interface = "" if interface: print("got interface") else: print("no interface name") - Fix this broken snippet so it runs without errors:
port_count = 48 print("Switch has " + port_count + " ports") - Stretch: write three lines that store an interface name, an admin status (boolean), and a description. Then print one line that says
"<name>: <up/down> - <description>"using an f‑string and a conditional expression (look up “Python ternary” if you’ve never seen one).
Answers
Show answer 1
>>> mtu = 1500
>>> print(f"MTU is {mtu} bytes")
MTU is 1500 bytes
Show answer 2
type(10 / 5) is <class 'float'> because / always returns a float in Python 3, even when the math divides evenly. type(10 // 5) is <class 'int'> because // is integer (floor) division and preserves the int type.
Show answer 3
Prints no interface name. An empty string "" is falsy, so the if branch is skipped and the else runs. This is the idiomatic Python way to test “do I have a non‑empty value?”
Show answer 4
Two clean fixes — pick the f‑string version in real code:
port_count = 48
print(f"Switch has {port_count} ports") # idiomatic
# or, less cleanly:
print("Switch has " + str(port_count) + " ports") # explicit conversion
Python won’t auto‑convert int to str during + — it raises TypeError instead, which is by design. Implicit conversion is the source of half the world’s bugs.
Show answer 5
name = "Gi0/1"
admin_up = True
description = "Uplink to core"
print(f"{name}: {'up' if admin_up else 'down'} - {description}")
# Gi0/1: up - Uplink to core
The 'up' if admin_up else 'down' is Python’s ternary expression — it evaluates to one of the two strings depending on the boolean. Useful any time you want a quick A‑or‑B inside an f‑string.
Coming tomorrow
Day 3: Strings, f‑strings & Slicing — Parsing IPs, MACs, and Banner Output. We’ll take messy CLI output and chop, split, and reformat it with nothing but built‑in string methods. By the end of tomorrow you’ll be able to extract the second octet of an IP, normalize a Cisco MAC like aabb.ccdd.eeff into colon notation, and trim a banner motd in three lines.