Skip to content

Loops

In this lesson, we'll revisit last week's list challenge and see how we can make it more efficient by using loops instead of hardcoding the variables. But first, let's look at a simple example to understand how for loops work.

Introduction to for-loops

devices = [
    "router2",
    "router17",
    "switch11",
]

for device in devices:
    print(f"{device = }")
Output
device = 'router2'
device = 'router17'
device = 'switch11'

When you read a loop like this, you can think of it as saying:
for each device in the list() of devices, print() the device

You may have noticed the indented code block under the for loop. This block is called the loop body and contains the code that is executed for each iteration of the loop.

What happens in this code example is that the for loop iterates over each item in the list. The device variable is assigned the value of each item in the list and then the loop executes the loop body. This process continues until all items in the list have been processed. You don't need to know how many items are in the list; the loop will handle that for you.

If we were to write this code without a loop, it would look like this:

device = devices[0]
print(f"{device = }")

device = devices[1]
print(f"{device = }")

device = devices[2]
print(f"{device = }")

Using a loop makes the code more efficient and easier to maintain. We can add or remove devices from the list without changing the loop, unlike the hardcoded version where we would need to update the code for each device as the number of indexes changes.

Original Challenge

We have a list of RFC1918 networks and a destination IP with a port. Our goal is to create access-list entries for each network.

Comma-separated values
rfc1918 = """
10.0.0.0,0.255.255.255,permit
172.16.0.0,0.0.15.255,permit
192.168.0.0,0.0.255.255,permit
"""

destination = "192.168.22.12,443"

We want the final output to look like this:

access-list 100 permit ip 10.0.0.0 0.255.255.255 host 192.168.22.12 eq 443
access-list 100 permit ip 172.16.0.0 0.0.15.255 host 192.168.22.12 eq 443
access-list 100 permit ip 192.168.0.0 0.0.255.255 host 192.168.22.12 eq 443

A new spin

Like we did in the original challenge, we can split the destination and networks into their components. However, instead of hardcoding the variables, we can use loops to handle any number of networks, like we just saw in the simple example in the top of the page.

Before we do so, let's create a data type that is easier to work with. We can split the destination and networks into lists of strings.

First, let's use list unpacking to split the destination into its components - the split() list method will return a list of strings that we can unpack into variables.

unpacking the destination
dest_ip, dest_port = destination.split(",")

Next, we can split the RFC1918 networks into a list of strings using the split() string method. This will return a list of strings that we can loop through.

Split the RFC1918 networks
# Split the RFC1918 networks into a list of strings
networks = rfc1918.strip().split("\n")

Now that we have the destination and networks split into lists of strings, we can loop through the networks and split each network into its components. We can then print the access-list entry for each network. The advantage of this approach is that we can handle any number of networks without hardcoding variables.

Loop through the networks
1
2
3
for network in networks:
    ip, wildcard, action = network.split(",")
    print(f"access-list 100 {action} ip {ip} {wildcard} host {dest_ip} eq {dest_port}")

Summary

Key Points

  • Use loops to handle repetitive tasks efficiently.
  • Splitting strings into components allows for dynamic processing.
  • Combining loops with string splitting, and unpacking can simplify complex tasks and make the code more readable.

By using loops, we can efficiently handle any number of networks without hardcoding variables. This approach makes our code more flexible and easier to maintain.

Try It Yourself

Modify the code to include additional actions or different network ranges. Experiment with different destination IPs and ports to see how the access-list entries change.

Congratulations on enhancing your Python skills with loops! Keep practicing - the more you code, the better you'll get.

Full Example
rfc1918 = """
10.0.0.0,0.255.255.255,permit
172.16.0.0,0.0.15.255,permit
192.168.0.0,0.0.255.255,permit
"""

destination = "192.168.22.12,443"

dest_ip, dest_port = destination.split(",")

networks = rfc1918.strip().split("\n")

for network in networks:
    ip, wildcard, action = network.split(",")
    print(f"access-list 100 {action} ip {ip} {wildcard} host {dest_ip} eq {dest_port}")