Sometimes, it is useful to make some operations on Data Structures and return the same Data Structure. Examples may include squaring every element of a collection, constructing a lookup table and so on. Python provides an easier syntax for doing these tasks. Let's understand comprehension techiniques by solving some problems
Given a list of integers, Create a new list containing their squares
C like approach
In [3]:
num = [10,8,3,5,2,7,0,1,4,9,6]
num
Out[3]:
In [6]:
def square_classic_approach(x):
"""
Input: x - List of Integers
Return: A list containing squares of each element of list
"""
squared = [] # Empty list
for i in range(len(num)): # Equivalent to for(i=0;i<num;i++)
squared.append(num[i]**2) # Power operator
return squared
In [7]:
square_classic_approach(num)
Out[7]:
In [13]:
def square_pythonic_approach(x): # Pythonic! :P
"""
Input: x - List of Integers
Return: A list containing squares of each element of list
"""
return [ num**2 for num in x ]
In [9]:
square_pythonic_approach(num)
Out[9]:
In [23]:
def square_if_even_classic_approach(x):
"""
Input: x - List of Integers
Return: A list containing squares of each element of list if element is even
"""
squared = [] # Empty list
for i in range(len(x)): # Equivalent to for(i=0;i<num;i++)
if x[i] % 2 == 0:
squared.append(x[i]**2) # Power operator
else:
squared.append(x[i])
return squared
In [24]:
square_if_even_classic_approach([10,9,2,4,5,67])
Out[24]:
Observe how list is created and passed on the fly
In [16]:
def square_if_even_pythonic_approach(x): # Pythonic! :P
"""
Input: x - List of Integers
Return: A list containing squares of each element of list if element is even
"""
return [ num**2 if num % 2 == 0 else num for num in x ]
In [17]:
square_if_even_pythonic_approach(([10,9,2,4,5,67]))
Out[17]:
In [31]:
def vowels_in(string):
"""
Input: string - a string
Return: List of vowels occuring in string
Example:
>>> vowels_in('Apple`)
['a','e']
"""
# We use a set because it stores unique elements
l_string = str.lower(string) # Converting to unique form
vowel_set = {c for c in l_string if c in 'aeiou'} # Note the imposal of condition
return sorted(list(vowel_set))
In [29]:
vowels_in('Apple')
Out[29]:
In [30]:
vowels_in('Karnataka')
Out[30]:
Above function can be written in more compact form
In [32]:
def vowels_in_compact(string):
"""
Input: string - a string
Return: List of vowels occuring in string
Example:
>>> vowels_in('Apple`)
['a','e']
"""
return sorted(list({c for c in str.lower(string) if c in 'aeiou'}))
In [33]:
vowels_in_compact('violin')
Out[33]:
In [36]:
def alphabet_occurance_count(string):
"""
Input: a string
Output: the number of occurance od f each character in the string
"""
return {x:string.count(x) for x in string}
In [38]:
alphabet_occurance_count("Hello from Notebook")
Out[38]:
In [39]:
import this
Obviously, this is Zen
Now let's have a look at other things in this module
In [40]:
this.c
Out[40]:
In [41]:
this.d
Out[41]:
It looks like a mapping from one character to another... Hmm... Interesting!
In [42]:
this.i
Out[42]:
In [43]:
this.s
Out[43]:
Wow!...Looks like encoded text.
We will decode it using this.d mapping
In [47]:
decoded = ''.join([this.d[c] if str.isalnum(c) else c for c in this.s]) # join() joins the iterable with string
print(decoded)
This is again Zen of Python!
In fact this module uses a function to build the Translation Table d in it's __init.py__ to print the Zen. The encoding done here is rot13 encoding. We will look about modules in upcoming chapters.
In [53]:
def fibonacci_recursive(n,first=0,second=1):
return [] if n == 0 else [first] + fibonacci_recursive(n - 1, second, first + second)
In [54]:
fibonacci_recursive(5)
Out[54]:
lambdasIn Python, functions are also objects. It means that you can pass them to other function like a variable. This flexibility of functions allows us to do many useful tasks. filtering a collection is one of them.
In [55]:
x = [0,1,3,5,8,7,6]
In [57]:
evens = [i for i in x if i%2 == 0]
evens
Out[57]:
filter with functionsfilter function takes a list and a function returning bool as argument and filter's the list, returns the iterator through filtered list. One can use list() to convert iterator to a list
Usage
result = list(filter(condition,collection))
condition is a boolean function that takes an element as input
In [58]:
def is_even(item):
return item % 2 == 0
In [61]:
list(filter(is_even,x))
Out[61]:
In previous example, we passed a function object to filter(). The same case happens in many situations. In some cases function to be passed might be too short like is_even(). In this case lambdas can be used. lambdas create function in place.
Usage:
function_name = lambda argument_list : executable_statements
This has the same effect as that of
def function_name(argument_list):
executable_statements
Now our is_even function can be defined in terms of lambdas
is_even = lambda x : x % 2 == 0 # Note that return may be omitted
If multi-line statements are needed, Statements can be put inside ()s or line can be extended with \s
In [62]:
list(filter(lambda x: x % 2 == 0,x))
Out[62]:
Lambdas are a fundamental concept of Functional Programming where every task is achieved via a function. They constitute the basis of a branch of Mathematics and Computation Theory called $\lambda$ calculus.
As a final thought, we shall see Recursive Fibonacci Generator in terms of lambdas
In [5]:
fibonacci_lambda = \
lambda n,first=0,second=1 :\
[] if n == 0 \
else \
[first] + fibonacci_lambda(n - 1, second, first + second)
In [6]:
fibonacci_lambda(4)
Out[6]:
Note that lines are broken with \