# An Introduction to Python List Comprehensions

Python list comprehensions offer a concise method of interacting with each element of a list. Even though they’ve been available since Python 2.0, their syntax often demotivates people from using them. This article aims to introduce List Comprehensions in a friendly way and offer you one more Python feature to add to your scripting toolbox.

## What is a List Comprehension

According to Python 3.7’s documentation, list comprehensions: […] provides a concise way to create lists. Common applications are to make new lists where each element is the result of some operations applied to each member of another sequence or iterable or to create a subsequence of those elements that satisfy a certain condition.

## Simple List Comprehension Example

The official list comprehension definition and its example may not be immediately clear. Let’s use an alternative example. Let’s say we had the numbers 0 through 5 and we wanted to multiply each number by 2. This means the numbers 0, 1, 2, 3, 4, and 5 are our multiplicands and 2 is our multiplier. We know the multiplication operations should be 0*2, 1*2, 2*2, 3*2, 4*2, and 5*2. The products of the multiplication operations should be 0, 2, 4, 6, 8, and 10.

In Python, we can use a list comprehension to perform the same calculation. Let’s describe our objective again but in a way that lends itself to scripting: for each, individual multiplicand (or number) in our multiplicands 0-5, we want to multiply by 2. Here’s the Python code and result:

```>>> multiplicands = [0, 1, 2, 3, 4, 5]
>>> multiplier = 2
>>> products = [number*multiplier for number in multiplicands]
>>> products
[0, 2, 4, 6, 8, 10]```

Our first line of code defined the list of multiplicands, 0-5. Our second line of code defined our multiplier, 2. Our third line of code defined the Python list comprehension, which performed our multiplication. The final line of code simply returned our product values.

## More Complex List Comprehension Example

It’s possible I became consumed with excitement and copied the entire list of dog breeds from a Wikipedia page into a spreadsheet and then used cell formulas to generate the syntax for an equivalent Python list. Furthermore, a few important notes about the data set:

• There are special characters like an apostrophe; therefore, do not change the double quotes to single quotes/apostrophes unless you know what you’re doing.
• There are international characters that cannot be represented in ASCII. We’ll revisit this soon in our example.

## Source Code:

```# Author: Jeoffri Davis
# Purpose:
#       - Example of using Python List Comprehensions
# Tested With:
#       - Python 3.7
#       - MacOS Mojave
# Inputs:
#       - All inputs are self-contained
# Outputs:
#       - Two different lists for Heelers
#       - One list for breed names containing international characters
# Define a massive list of dog breeds. Not attempting to contain
# doggo love in PEP 8 coding style.
,"Russell Terrier","Saarloos Wolfdog","Sabueso Español","Sabueso fino Colombiano","Saint Bernard","Saint John's water dog","Saint-Usuge Spaniel","Sakhalin Husky","Salish Wool Dog","Saluki","Samoyed","Sapsali","Šarplaninac","Schapendoes","Schillerstövare","Schipperke","Schweizer Laufhund","Schweizerischer Niederlaufhund","Scotch Collie","Scottish Deerhound","Scottish Terrier","Sealyham Terrier","Segugio Italiano","Segugio Maremmano","Seppala Siberian Sleddog","Serbian Hound","Serbian Tricolour Hound","Seskar Seal Dog","Shar Pei","Shetland Sheepdog","Shiba Inu","Shih Tzu","Shikoku","Shiloh Shepherd","Siberian Husky","Silken Windhound","Silky Terrier","Sinhala Hound","Skye Terrier","Sloughi","Slovakian Wirehaired Pointer","Slovensky Cuvac","Slovensky Kopov","Smålandsstövare","Small Münsterländer","Small Greek Domestic Dog","Soft-Coated Wheaten Terrier","South Russian Ovcharka","Southern Hound","Spanish Mastiff","Spanish Water Dog","Spinone Italiano","Sporting Lucas Terrier","Stabyhoun","Staffordshire Bull Terrier","Standard Schnauzer","Stephens Cur","Styrian Coarse-haired Hound","Sussex Spaniel","Swedish Lapphund","Swedish Vallhund","Tahitian Dog","Tahltan Bear Dog","Taigan","Taiwan Dog","Talbot Hound","Tamaskan Dog","Teddy Roosevelt Terrier","Telomian","Tenterfield Terrier","Terceira Mastiff","Thai Bangkaew Dog","Thai Ridgeback","Tibetan Mastiff","Tibetan Spaniel","Tibetan Terrier","Tornjak","Tosa","Toy Bulldog","Toy Fox Terrier","Toy Manchester Terrier","Toy Trawler Spaniel","Transylvanian Hound","Treeing Cur","Treeing Tennessee Brindle","Treeing Walker Coonhound","Trigg Hound","Tweed Water Spaniel","Tyrolean Hound","Cimarrón Uruguayo","Vanjari Hound","Villano de Las Encartaciones","Villanuco de Las Encartaciones","Vizsla","Volpino Italiano","Weimaraner","Welsh Corgi, Cardigan","Welsh Corgi, Pembroke","Welsh Sheepdog","Welsh Springer Spaniel","Welsh Terrier","West Highland White Terrier","West Siberian Laika","Westphalian Dachsbracke","Wetterhoun","Whippet","White Shepherd","Wirehaired Pointing Griffon","Wirehaired Vizsla","Xiasi Dog","Xoloitzcuintli","Yakutian Laika","Yorkshire Terrier"]
def isHeeler(breed: str):
"""This function lets us define more robust logic for
determining whether a dog is a Heeler breed. This comes
in handy when dog breeds have multiple nicknames.
"""
if 'Heeler' in breed or breed == 'Australian Cattle Dog':
return True
else:
return False
def isAscii(breed: str):
"""This function checks if a breed name can be encoded
with ASCII, which is a character set that supports all
standard alphanumeric characters found in American English.
If the breed name cannot be encoded with ASCII, it is a
good indicator that the breed name contains international
characters. While we like our dogs well traveled, we
would run into encoding issues if we expand our script to
integrate with other systems or solutions that expect
ASCII encoding.
"""
result = True
try:
breed.encode('ascii')
except UnicodeEncodeError as caught_exception:
result = False
return result
# List comprehension that searches the list contained
# in variable "dogs", finds all breeds with the word
# 'Heeler' in it and saves the matching breeds to a
#  a new list called "heelers1"
heelers1 = [dog for dog in dogs if 'Heeler' in dog]
# List comprehension that uses the isHeeler function
# for its conditional logic. Using a function keeps
# the list comprehension concise.
heelers2 = [dog for dog in dogs if isHeeler(dog)]
# List comprehension that finds all dog breeds with
# international characters in its name. Sometimes
# in scripting it's good to watch for international
# characters because they can lead to encoding issues.
# You normally wouldn't force ASCII encoding but its
# character set is familiar, which helps understand
# the concept of encoding.
international_doggos = [dog for dog in dogs if not isAscii(dog)]
international_doggos = [dog for dog in dogs if not isAscii(dog)]
print("\nBreeds names containing the word 'Heeler':" + str(heelers1))
print("\nMore robust list of Heeler breeds:" + str(heelers2))
print("\nBreed names containing international characters:" + str(international_doggos))```

## Output

```Breeds names containing the word 'Heeler':['Blue Heeler', 'Lancashire Heeler']
More robust list of Heeler breeds:['Australian Cattle Dog', 'Blue Heeler', 'Lancashire Heeler']
Breed names containing international characters:['Alano Español', 'Anglo-Français de Petite Vénerie', 'Basset Artésien Normand', 'Bichon Frisé', 'Briquet Griffon Vendéen', 'Cão da Serra de Aires', 'Cão de Castro Laboreiro', 'Cão de Gado Transmontano', 'Cão Fila de São Miguel', 'Chien Français Blanc et Noir', 'Chien Français Blanc et Orange', 'Chien Français Tricolore', 'Galgo Español', 'Gran Mastín de Borínquen', 'Grand Anglo-Français Blanc et Noir', 'Grand Anglo-Français Blanc et Orange', 'Grand Anglo-Français Tricolore', 'Grand Basset Griffon Vendéen', 'Grand Griffon Vendéen', 'Hamiltonstövare', 'Kromfohrländer', 'Kurī', 'Large Münsterländer', 'Löwchen', 'Magyar agár', 'Petit Basset Griffon Vendéen', 'Phalène', 'Pražský Krysařík', 'Sabueso Español', 'Šarplaninac', 'Schillerstövare', 'Smålandsstövare', 'Small Münsterländer', 'Cimarrón Uruguayo']```

## How List Comprehensions Can Apply to LogicMonitor

I often find myself using List Comprehensions when programmatically managing LM portals through the LM REST API. Two examples are:

1. Maximizing REST API and data processing efficiency. Rather than submitting multiple API calls with filter query parameters, I can use one REST API call to pull all device groups and then filter the results into subsets of data using Python list comprehensions. Getting equivalent subsets directly from the REST API would require multiple API calls, which would be slower than accessing local memory, and, risk API usage throttling.
2. Sanity checking CSV files used to build device groups or dashboards in a LogicMonitor portal. During Professional Services engagements where I need to help a customer, especially MSPs, onboard, I will often have them define their desired device and dashboard group structure in a CSV. Then I can use the LM REST API to build out their portal. There are some restricted special characters as well as character count limitations. These can both be checked early in the Python script with a list comprehension before making REST API calls that would ultimately fail.

## Conclusion

Python List Comprehensions can offer concise, yet powerful, list manipulation. You can perform operations on each element in a list and even include conditions as to when the operations should take place. I commonly use list comprehensions to cache data returned from the LogicMonitor REST API and split it into subsets. I also reach for list comprehensions when I need to sanity check CSV files before using them for other operations.

LogicMonitor powers monitoring of global business services you probably use every day. Operating at that level takes flexibility. That’s why LogicMonitor DataSources support Python, Groovy, PowerShell and any other language as long as you configure it in your collector host environment.