Wednesday, May 20, 2020

Python list comprehensions

Python list comprehensions

List Comprehensions

List comprehensions are small syntactic constructs in Python. We can produce a new list from another list by applying these constructs to each element in the list. 

This tutorial explains the use and applications of these expressions.

The general form of a list comprehension is,

[<expression> for <element> in <iterable>] 


[<expression> for <element> in <iterable> if <condition>] 

For example,

squar=[num*num for num in ls]

#[25, 49, 81, 121]  

Each element is passed through the expression. The entire result is returned at once in the new list. List comprehensions evaluate entire results immediately. The memory requirements are proportionate to the iterator size.

# convert a list elements to uppercase characters
u=[l.upper() for l in "python programming"]
# ['P', 'Y', 'T', 'H', 'O', 'N', ' ', 'P', 'R', 'O', 'G', 'R', 'A', 'M', 'M', 'I', 'N', 'G']

# Strip off any space from the end of strings in a list
compact=[w.strip(' ') for w in ['green ', 'woods ', 'black', 'woods']]
# ['green', 'woods', 'black', 'woods']

# Arrange letters in words in an alphabetical order
sentence = "Python is awesome programming langauge"
t=["".join(sorted(word,key = lambda x: x.lower())) for word in sentence.split()]
# ['hnoPty', 'is', 'aeemosw', 'aggimmnoprr', 'aaegglnu']

the if-else statement can be supplied to apply some condition. For example,

nls=[x*x if x%2==1 else x*x*x for x in ls]

#[1, 8, 9, 64, 25]


ls=[x if x in 'aeiou' else '*' for x in 'apple']

#['a', '*', '*', '*', 'e']

The if-else statement must occur before for statement, otherwise, SyntaxError will occur.

In-place Mutation and list comprehension Side Effects 

We need to understand the difference between functions called for their side effects (mutating, or in-place functions) which usually return None, and functions that return an interesting value.

A pure function takes an object and returns some object. However, in-place function updates the existing object, this is known as a side effect. For example, a list.sort() method sorts a list in-place(it means it modifies the actual list) and returns None. So, the sort() method does not work as expected,

ls=[item.sort() for item in [[2, 1], [4, 3], [0, 1]]]

#[None, None, None]

instead, we can use

ls=[sorted(item) for item in [[2, 1], [4, 3], [0, 1]]]

#[[1, 2], [3, 4], [0, 1]]

because the sorted() method does not change the actual list.

There can be situations when comprehensions reach undesirable length. For example, 

x for x
in 'python'
if x not in 'java'