List Comprehension and Lambda functions

LIST COMPREHENSION
AND
LAMBDA FUNCTIONS

A quick guide to understand how to use them and their differences in Python

To understand list comprehension, we must first understand how we traditionally loop through any particular collection/data structure.  When we think of a data structure, we are generally thinking about either a list, dictionary, tuple, or set (all of which are built into Python). Each element has its own location in memory, and we store all of the memory location pointers inside the data structure (assigning it an index value, or key for dictionaries). It’s important to note that we can also loop through string data types as they are essentially a collection of characters. Python allows us to loop through anything that is an iterable object, or an object that belongs to a class containing the __iter__() method. We can see if an object is iterable by running a simple print(dir(variable))), this will print all of the associated methods of the object/data type we are working with. Below you will see that a set is indeed iterable (method is highlighted):

nums = {1, 2, 3, 4, 5, 6, 7}
print(dir(nums)) # running the dir() function on the nums set

“””here is a just a part of the output”””

['__and__', '__class__', '__class_getitem__', '__contains__', '__delattr__', '__dir__', '__doc__', '__eq__', '__format__', '__ge__', '__getattribute__', '__gt__', '__hash__', '__iand__', '__init__', '__init_subclass__', '__ior__', '__isub__', '__iter__',

So now that we know we are able to loop through this object, lets go over  3 different, but common for loops that we can perform on the new nums list.

nums = [200, 700, 1200, 980, 430]
# gives us just the value
for i in nums:  
    print(i)
# gives us just a number/index
for i in range(len(nums)):  
    print(i)
# gives us the index and the value
for index, value in enumerate(nums):  
    print(index, value)
 0 200      
 1 700
 2 1200
 3 980
 4 430

Whenever there is a case when you need the index number and the element, please utilize enumerate, and furthermore, avoid the range() style for loop. Perhaps there is a scenario where we need to perform a certain action, or calculation on the elements in our list, while also appending them to a new list. For example, we want to square  each value in our list (if they are integers/floats) or perhaps we want to concatenate some extra text to a list of string data types. This would require at the least three lines of code, and this is where list comprehension comes into play.
Let us look at performing this action without list comprehension, and then with list comprehension included.

# original list (we will perform action on its elements)
nums = [200, 700, 1200, 980, 430]  
# empty list to be populated with nums elements squared
nums2 = []  
for i in nums:
     nums2.append(i * i)

We can see that at the very least it takes three lines of code to perform this task, and that’s without any conditions (which will increase our lines of code even more!).
Lets reduce this down to one line of code by using list comprehension:

# original list (we will perform action on its elements)
nums = [200, 700, 1200, 980, 430]  
# list with "for" loop inside of it
nums2 = [i * i for i in nums]  

This is a huge difference, and because list comprehension is quite popular in the Python community, many would argue that it increases the readability of the code . What’s amazing is that we can include some minor conditionals all in the same line. But we must understand that one conditional/if statement must go after we declare the for loop, and two conditional statements must go before the for-loop declaration. We cannot use an elif statement, only if/else.

# original list (we will perform action on its elements)
nums = [200, 700, 1200, 980, 430]  
# only perform task if i is greater than 700 (1 condition belongs at the end)
nums2 = [i * i for i in nums if i > 700]  
# (2 conditions)
nums2 = [i * i if i > 700 else i * 3 for i in nums]  

What is lambda function?

We have discussed list comprehension, but now we must address lambda functions. A lambda function is a more anonymous function, meant to be used for a task and then thrown away. Generally, lambdas are used for functions that take another function for an argument. The lambda allows us to write a function directly into the call of another function. Two very popular functions that accept lambdas are map() and filter().  Let us take a quick look at the difference between a function and a lambda:

def add(x, y):
   return x + y

add = lambda x, y: x + y

You may notice that lambda does not require the return keyword, which is because it automatically returns the expression after the colon: these are more like 1 liner’s (although some developers use nested lambda functions). Time for us to implement a lambda inside of a map function.

numbers = [12, 90, 67, 13, 45]

print(list(map(lambda x: x ** 2, numbers))) 
# returns  [144, 8100, 4489, 169, 2025]

Above you can see an example of map where we perform exponential math on every value inside of the numbers list, then we convert the map to a list, and lastly, we print the list. Remember that the inner most function works first (excluding the lambda). We should now take a look at using lambdas with a filter function (which will evaluate each element and return if true, otherwise return nothing or false). For filter to work properly we need to utilize a Boolean expression with our lambda function versus a mathematical expression.

numbers = [12, 90, 67, 13, 45]

print(list(filter(lambda x: x > 45, numbers))) 
# output 
[90, 67] 

# We add conditionals to a lambda
print(list(filter(lambda x: x if (x > 45) else (x < 13), numbers)))
#Output
[90, 67, 45]

To be clear lambdas are useful, but this looks very similar to a list comprehension. List comprehensions are more pythonic and easier to read.

Image

Practity
Register New Account
Shopping cart