top
upGrad KnowledgeHut SkillFest Sale!

Search

Python Tutorial

Different programming languages take different approach towards programming. These approaches are also called programming paradigms. Imperative, object oriented, declarative and functional paradigms are widely adapted. Python is a multi-paradigm language. It supports imperative, object oriented, as well as functional programming approach.Functional programming paradigm recommends dividing the programming logic into set of functions that only take input and produce output not that affects the output produced for a given input. In this chapter we discuss certain features of Python which help in writing functional-style programs.Lambda functionThe def keyword is used to define a named function. Lambda keyword is used to create anonymous function. Usually such a function is created on the fly and meant for one-time use. The general syntax of lambda is as follows:lambda arg1, arg2… : expressionA lambda function can have any number of arguments but there’s always a single expression after : symbol. The value of expression becomes return value of lambda function. For example>>> add=lambda a,b:a+bAn anonymous function is declared with lambda keyword that receives a and b and returns a+b.. The anonymous function object is assigned to identifier called add. We can now use it as a regular function call>>> print (add(2,3 5Note that the above lambda function is equivalent to a normal function declared using def keyword as below:>>> def add(a,b); return a+b >>> print (add(2,3)) 5However, body of lambda function can have only one expression. Therefore it can substitute a normal function having complex logic involving conditionals, loops etc.In Python, function is a called a first order object, because function can also be used as argument, just as number, string, list etc. A lambda function is often used as argument function to functional programming tools such as map(), filter() and reduce() functions.Recursion:A function can call any other function, including itself also. Function is said to be recursive if it calls itself. Recursion is used when a process is defined in terms of itself. Obviously, a recursive call by function to itself causes an infinite loop. Hence recursive call is always conditional. Recursive approach provides a very concise solution to complex problem having many iterations.In general, any iterative process can be expressed in the form of recursion. It takes a bit of expertise to write recursive equivalent of classical loop. The most popular example of recursion is calculation of factorial. A layman's definition of factorial of a number is multiplication of all numbers from 1 to itself. However, in mathematics factorial is defined as:n! = n X (n-1)!Here we have used factorial itself to define factorial. Such problems are ideally suited to be expressed recursively.We can perform this calculation using a loop as per following code:>>> def factorial(x): f=1 for i in range(1, x+1): f=f*i return f >>> factorial(5) 120Now we shall try to write recursive equivalent of above loop. Look at mathematical definition of factorial once again.n!=nX(n-1)!Substitute n with 5. The expression becomes5!=5X4! = 5X4X3! = 5X4X3X2! = 5X4X3X2X1! = 5X4X3X2X1 = 120Let us see graphically the step by step process of computing factorial value of 5.Above process involves successively performing factorial calculation of number by decrementing the number till it reaches 1. Following is recursive function to calculate factorial>>> def factorial(n):        if n == 1:        print (n)        return 1        else:        print (n,'*', end=' ')        return n * factorial(n-1) >>> factorial(5) 5 * 4 * 3 * 2 * 1 120First time, the factorial function is called with 5 as argument. The function recursively calls itself, with reducing value. Functions return to their earlier call after the number reaches 1. Return value of first call is cumulative product of return values of all calls.IteratorPython uses iterators are implicitly while working with collection data types such as list, tuple or string. That's why these data types are quite  called iterables.We normally use for loop to iterate through an iterable as follows:for element in  sequence:     print (element)An iterator an object represents a data stream that returns one element at a time. It follows iterator protocol which requires it to support  __iter__() and __next__() methods. Python’s built-in method iter() implements __iter__() method. It receives an iterable and returns iterator object.>>> iter("aa") <str_iterator object at 0x05A73190> >>> iter([1,2,3]) <list_iterator object at 0x05CE5E30> >>> iter((1,2,3)) <tuple_iterator object at 0x05CE5E50> >>> iter({}) <dict_keyiterator object at 0x05CDD480> >>> iter(100) Traceback (most recent call last):  File "<pyshell#7>", line 1, in <module>    iter(100) TypeError: 'int' object is not iterableNote that if the argument is not iterable, TypeError is encountered.Iterator object has __next__() method. Every time it is called, it returns next element in iterator stream. When the stream gets exhausted, StopIteration error is raised.>>> string="computer" >>> it=iter(string) >>> it.__next__() 'c' >>> it.__next__() 'o' >>> it.__next__() 'm' >>> it.__next__() 'p' >>> next(it) 'u' >>> next(it) 't' >>> next(it) 'e' >>> it.__next__() 'r' >>> it.__next__() Traceback (most recent call last):  File "<pyshell#10>", line 1, in <module>    it.__next__() StopIterationThe built-in function next() internally calls __next__() method on iterator object. Hence it.__next__()is equivalent to next(it).A for loop over any iterable object, actually implements iterator protocol internally as  per the following process:>>> string="computer" >>> it=iter(string) >>> while True: try: char=next(it) print (char) except StopIteration: breakThis is equivalent to using a for loop as below:>>> for char in 'computer': print (char)The 'try' and 'except' keywords are used in exception handling, which will be discussed in a subsequent chapter.GeneratorA generator is a special type of function. Even though it looks like a normal function , it doesn’t return a single value. It returns an iterator object returning stream of values. In a generator function yield statement is used rather than return statement found in a normal function.The generator is called just like a normal function. It pauses on encountering yield keyword. The yielded value is returned to calling environment. However, local variables and their states are saved internally. Function resumes when __next__() method of iterator is called. The function finally terminates when __next__() or next() raises StopIteration.In following example function generator() acts as a generator. It yields one character at a time from the string sequence successively on every call of next()def generator(x):        for i in x:                print ("yielding", i)                yield i gen=generator('Hello') while True:        try:                print ("received ",next(gen))                print ("next character")        except StopIteration:                print ("end of generator")                breakOutput:yielding H received  H next character yielding e received  e next character yielding l received  l next character yielding l received  l next character yielding o received  o next character end of generatorWe can use for statement to traverse elements over generator. In this case next() function is called implicitly and StopIteration is also automatically taken care of.def generator(x):        for i in x:                print ("yielding",i)                yield i gen=generator("hello") for char in gen:        print ("received ",char)        print ("next character") print ("end of generator")In case of generator elements are generated dynamically. Since next item is generated only after first is consumed, it is more memory efficient than iterator.List comprehensionList comprehension techniques follow mathematical set builder notation. It is a very concise and efficient mechanism of creating new list by performing a certain process on each item of existing list. List comprehension is considerably efficient than processing a list by for loop.Suppose we want to compute square of each number in a list and store squares in another list object. We can do it by a for loop as shown below:squares=[] for num in range(6):         squares.append(pow(num,2)) print (squares)The squares list object is displayed as follows:[0, 1, 4, 9, 16, 25]List comprehension technique easily achieves same result more efficiently. List comprehension statement uses following syntax:newlist = [x for x in sequence]We use above format to construct list of squares using list comprehension.>>> squares=[x*x for x in range(6)] >>> squares [0, 1, 4, 9, 16, 25]We can even generate a dictionary or tuple object as a result of list comprehension.>>> [{x:x*10} for x in range(1,6)] [{1: 10}, {2: 20}, {3: 30}, {4: 40}, {5: 50}]Nested loops can also be used in a list comprehension expression. To obtain list of all combinations of items from two lists:>>> [{x:y} for x in range(1,3) for y in range(100,300,100)] [{1: 100}, {1: 200}, {2: 100}, {2: 200}]The resulting list stores all combinations of one number from each listWe can even have if condition in list comprehension. Following statement will result in list of all non-vowel alphabets in a string.>>> consonants=[char for char in "Beautiful" if char not in ['a','e','i','o','u']] >>> consonants ['B', 't', 'f', 'l']The itertools moduleThe module of Python’s standard library consists of more efficient and fast iteration tools.count() returns an iterator of evenly spaced valuescycle() returns each element from given iterable and saves its copy and returns repeatedly forming infinite loop.repeat() This function returns the object argument repeatedly.accumulate() applies a function to successive items in a listdropwhile() returns an iterator by dropping elements from iterable as long as predicate function argument returns true.filterfalse() returns an iterator by filtering out elements for whom the predicate function results False.islice() build an iterator by selecting certain elements from iterable.product() generates an iterator which is a Cartesian product of elements in input sequences.permutations() yields all possible permutations of elements in input iterable.combinations() yields all possible combinations of elements in input iterable.map() functionThebuilt-in  map() function is especially useful where it is required to process each item from one or more iterable sequences (string, list, tuple or dictionary). It subjects each element in the iterable to another function which may be either a built-in function, a lambda function or a user-defined function and returns the mapped object. The map() function needs two arguments:map(Function, Sequence(s))In following example we first define a function to compute factorial of a number.def factorial(n):         if n == 1:         return 1         else:         return n * factorial(n-1)The map() function applies it to each element in the numbers[] list. The map object is converted to generate squares[] list.numbers=[1,2,3,4,5] factmap=map(factorial,numbers) print (list(factmap))Output:[1,2,6,24,120]Instead of user-defined function, we now use factorial() function from math module and use it as argument to map() function.from math import factorial numbers=[1,2,3,4,5] factmap=map(factorial,numbers) print (list(factmap))Next example uses a lambda function as argument to map() function. The lambda function itself takes two arguments taken from two lists and returns first number raised to second.The resulting mapped object is then parsed to output list.powersmap=map(lambda x,y: x**y, [10,20,30], [4,3,2]) print (list(powersmap))Output:[10000, 8000, 900]filter() functionThe filter() function also receives two arguments, a function with Boolean return value and a sequence. Only the items for which the function returns True are stored in a filter object.In following example, a function isvowel() is defined which returns True if the character is a not a vowel (a, e,i or u), otherwise returns False. This function is used inside filter() along with a string containing few lines from 'zen of Python'. Vowels from the lines are filtered out and only consonants are returned.def isvowel(x):        for char in x:                if char in ['a','e','i','o','u']:                        return False        else:                return True string=''' Beautiful is better than ugly. Explicit is better than implicit. Simple is better than complex. Complex is better than complicated. Flat is better than nested. ''' consonants=list(filter(isvowel,string)) print (''.join(consonants))Output:Btfl s bttr thn gly. Explct s bttr thn mplct. Smpl s bttr thn cmplx. Cmplx s bttr thn cmplctd. Flt s bttr thn nstd.Lambda function can also be used as a filter. Following program use lambda function that filters all vowels from given string.string=''' Beautiful is better than ugly. Explicit is better than implicit. Simple is better than complex. Complex is better than complicated. Flat is better than nested. ''' consonants=list(filter(lambda x: x not in ['a','e','i','o','u'],string)) print (''.join(consonants))reduce() functionUnlike map and filter functions, reduce() is not a built-in function, but is defined in built-in functools module. It also needs two arguments, a function and an iterable. However it returns a single value. The argument function is applied to two successive items in the list from left to right. Result of the function in first call becomes first argument and third item in list becomes second. Cumulative result is the return value of reduce() function.In the example below, add() function is defined to return addition of two numbers. This function is used in reduce() function along with a range of numbers between 0 to 100. Output is sum of first 100 numbers.import functools def add(x,y):         return x+y num=functools.reduce(add, range(101)) print ('sum of first 100 numbers ',num)Output:sum of first 100 numbers  5050We can use a lambda function instead of user-defined add() function for the same output.num=functools.reduce(lambda x,y:x+y, range(101))The functool module of Python's standard library consists of more first order functions which act on or return other function.
logo

Python Tutorial

Python - Functional Programming

Different programming languages take different approach towards programming. These approaches are also called programming paradigms. Imperative, object oriented, declarative and functional paradigms are widely adapted. Python is a multi-paradigm language. It supports imperative, object oriented, as well as functional programming approach.

Functional programming paradigm recommends dividing the programming logic into set of functions that only take input and produce output not that affects the output produced for a given input. 

In this chapter we discuss certain features of Python which help in writing functional-style programs.

Lambda function

The def keyword is used to define a named function. Lambda keyword is used to create anonymous function. Usually such a function is created on the fly and meant for one-time use. The general syntax of lambda is as follows:

lambda arg1, arg2… : expression

A lambda function can have any number of arguments but there’s always a single expression after : symbol. The value of expression becomes return value of lambda function. For example

>>> add=lambda a,b:a+b

An anonymous function is declared with lambda keyword that receives a and b and returns a+b.. The anonymous function object is assigned to identifier called add. We can now use it as a regular function call

>>> print (add(2,3
5

Note that the above lambda function is equivalent to a normal function declared using def keyword as below:

>>> def add(a,b);
return a+b
>>> print (add(2,3))
5

However, body of lambda function can have only one expression. Therefore it can substitute a normal function having complex logic involving conditionals, loops etc.

In Python, function is a called a first order object, because function can also be used as argument, just as number, string, list etc. A lambda function is often used as argument function to functional programming tools such as map(), filter() and reduce() functions.

Recursion:

A function can call any other function, including itself also. Function is said to be recursive if it calls itself. Recursion is used when a process is defined in terms of itself. Obviously, a recursive call by function to itself causes an infinite loop. Hence recursive call is always conditional. Recursive approach provides a very concise solution to complex problem having many iterations.

In general, any iterative process can be expressed in the form of recursion. It takes a bit of expertise to write recursive equivalent of classical loop. The most popular example of recursion is calculation of factorial. A layman's definition of factorial of a number is multiplication of all numbers from 1 to itself. However, in mathematics factorial is defined as:

n! = n X (n-1)!

Here we have used factorial itself to define factorial. Such problems are ideally suited to be expressed recursively.

We can perform this calculation using a loop as per following code:

>>> def factorial(x):
f=1
for i in range(1, x+1):
f=f*i
return f


>>> factorial(5)
120

Now we shall try to write recursive equivalent of above loop. Look at mathematical definition of factorial once again.

n!=nX(n-1)!

Substitute n with 5. The expression becomes

5!=5X4! = 5X4X3! = 5X4X3X2! = 5X4X3X2X1! = 5X4X3X2X1 = 120

Let us see graphically the step by step process of computing factorial value of 5.

Above process involves successively performing factorial calculation of number by decrementing the number till it reaches 1. Following is recursive function to calculate factorial

>>> def factorial(n):    
   if n == 1:
       print (n)
       return 1    
   else:
       print (n,'*', end=' ')
       return n * factorial(n-1)
>>> factorial(5)
5 * 4 * 3 * 2 * 1
120

First time, the factorial function is called with 5 as argument. The function recursively calls itself, with reducing value. Functions return to their earlier call after the number reaches 1. Return value of first call is cumulative product of return values of all calls.

Iterator

Python uses iterators are implicitly while working with collection data types such as list, tuple or string. That's why these data types are quite  called iterables.

We normally use for loop to iterate through an iterable as follows:

for element in  sequence:

     print (element)

An iterator an object represents a data stream that returns one element at a time. It follows iterator protocol which requires it to support  __iter__() and __next__() methods. Python’s built-in method iter() implements __iter__() method. It receives an iterable and returns iterator object.

>>> iter("aa")
<str_iterator object at 0x05A73190>
>>> iter([1,2,3])
<list_iterator object at 0x05CE5E30>
>>> iter((1,2,3))
<tuple_iterator object at 0x05CE5E50>
>>> iter({})
<dict_keyiterator object at 0x05CDD480>
>>> iter(100)
Traceback (most recent call last):
 File "<pyshell#7>", line 1, in <module>
   iter(100)
TypeError: 'int' object is not iterable

Note that if the argument is not iterable, TypeError is encountered.

Iterator object has __next__() method. Every time it is called, it returns next element in iterator stream. When the stream gets exhausted, StopIteration error is raised.

>>> string="computer"
>>> it=iter(string)
>>> it.__next__()
'c'
>>> it.__next__()
'o'
>>> it.__next__()
'm'
>>> it.__next__()
'p'
>>> next(it)
'u'
>>> next(it)
't'
>>> next(it)
'e'
>>> it.__next__()
'r'
>>> it.__next__()
Traceback (most recent call last):
 File "<pyshell#10>", line 1, in <module>
   it.__next__()
StopIteration

The built-in function next() internally calls __next__() method on iterator object. Hence it.__next__()

is equivalent to next(it).

A for loop over any iterable object, actually implements iterator protocol internally as  per the following process:

>>> string="computer"
>>> it=iter(string)
>>> while True:
try:
char=next(it)
print (char)
except StopIteration:
break

This is equivalent to using a for loop as below:

>>> for char in 'computer':
print (char)

The 'try' and 'except' keywords are used in exception handling, which will be discussed in a subsequent chapter.

Generator

A generator is a special type of function. Even though it looks like a normal function , it doesn’t return a single value. It returns an iterator object returning stream of values. In a generator function yield statement is used rather than return statement found in a normal function.

The generator is called just like a normal function. It pauses on encountering yield keyword. The yielded value is returned to calling environment. However, local variables and their states are saved internally. Function resumes when __next__() method of iterator is called. The function finally terminates when __next__() or next() raises StopIteration.

In following example function generator() acts as a generator. It yields one character at a time from the string sequence successively on every call of next()

def generator(x):
       for i in x:
               print ("yielding", i)
               yield i
gen=generator('Hello')
while True:
       try:
               print ("received ",next(gen))
               print ("next character")
       except StopIteration:
               print ("end of generator")
               break

Output:

yielding H
received  H
next character
yielding e
received  e
next character
yielding l
received  l
next character
yielding l
received  l
next character
yielding o
received  o
next character
end of generator

We can use for statement to traverse elements over generator. In this case next() function is called implicitly and StopIteration is also automatically taken care of.

def generator(x):
       for i in x:
               print ("yielding",i)
               yield i
gen=generator("hello")
for char in gen:
       print ("received ",char)
       print ("next character")
print ("end of generator")

In case of generator elements are generated dynamically. Since next item is generated only after first is consumed, it is more memory efficient than iterator.

List comprehension

List comprehension techniques follow mathematical set builder notation. It is a very concise and efficient mechanism of creating new list by performing a certain process on each item of existing list. List comprehension is considerably efficient than processing a list by for loop.

Suppose we want to compute square of each number in a list and store squares in another list object. We can do it by a for loop as shown below:

squares=[]
for num in range(6):
        squares.append(pow(num,2))
print (squares)

The squares list object is displayed as follows:

[0, 1, 4, 9, 16, 25]

List comprehension technique easily achieves same result more efficiently. List comprehension statement uses following syntax:

newlist = [x for x in sequence]

We use above format to construct list of squares using list comprehension.

>>> squares=[x*x for x in range(6)]
>>> squares
[0, 1, 4, 9, 16, 25]

We can even generate a dictionary or tuple object as a result of list comprehension.

>>> [{x:x*10} for x in range(1,6)]
[{1: 10}, {2: 20}, {3: 30}, {4: 40}, {5: 50}]

Nested loops can also be used in a list comprehension expression. To obtain list of all combinations of items from two lists:

>>> [{x:y} for x in range(1,3) for y in range(100,300,100)]
[{1: 100}, {1: 200}, {2: 100}, {2: 200}]

The resulting list stores all combinations of one number from each list

We can even have if condition in list comprehension. Following statement will result in list of all non-vowel alphabets in a string.

>>> consonants=[char for char in "Beautiful" if char not in ['a','e','i','o','u']]
>>> consonants
['B', 't', 'f', 'l']

The itertools module

The module of Python’s standard library consists of more efficient and fast iteration tools.

count() returns an iterator of evenly spaced values
cycle() returns each element from given iterable and saves its copy and returns repeatedly forming infinite loop.
repeat() This function returns the object argument repeatedly.
accumulate() applies a function to successive items in a list
dropwhile() returns an iterator by dropping elements from iterable as long as predicate function argument returns true.
filterfalse() returns an iterator by filtering out elements for whom the predicate function results False.
islice() build an iterator by selecting certain elements from iterable.
product() generates an iterator which is a Cartesian product of elements in input sequences.
permutations() yields all possible permutations of elements in input iterable.
combinations() yields all possible combinations of elements in input iterable.

map() function

Thebuilt-in  map() function is especially useful where it is required to process each item from one or more iterable sequences (string, list, tuple or dictionary). It subjects each element in the iterable to another function which may be either a built-in function, a lambda function or a user-defined function and returns the mapped object. The map() function needs two arguments:

map(Function, Sequence(s))

In following example we first define a function to compute factorial of a number.

def factorial(n):    
    if n == 1:
        return 1    
    else:
        return n * factorial(n-1)

The map() function applies it to each element in the numbers[] list. The map object is converted to generate squares[] list.

numbers=[1,2,3,4,5]
factmap=map(factorial,numbers)
print (list(factmap))

Output:

[1,2,6,24,120]

Instead of user-defined function, we now use factorial() function from math module and use it as argument to map() function.

from math import factorial
numbers=[1,2,3,4,5]
factmap=map(factorial,numbers)
print (list(factmap))

Next example uses a lambda function as argument to map() function. The lambda function itself takes two arguments taken from two lists and returns first number raised to second.The resulting mapped object is then parsed to output list.

powersmap=map(lambda x,y: x**y, [10,20,30], [4,3,2])
print (list(powersmap))

Output:

[10000, 8000, 900]


filter() function

The filter() function also receives two arguments, a function with Boolean return value and a sequence. Only the items for which the function returns True are stored in a filter object.

In following example, a function isvowel() is defined which returns True if the character is a not a vowel (a, e,i or u), otherwise returns False. This function is used inside filter() along with a string containing few lines from 'zen of Python'. Vowels from the lines are filtered out and only consonants are returned.

def isvowel(x):
       for char in x:
               if char in ['a','e','i','o','u']:
                       return False
       else:
               return True
string='''
Beautiful is better than ugly.
Explicit is better than implicit.
Simple is better than complex.
Complex is better than complicated.
Flat is better than nested.
'''
consonants=list(filter(isvowel,string))
print (''.join(consonants))

Output:

Btfl s bttr thn gly.
Explct s bttr thn mplct.
Smpl s bttr thn cmplx.
Cmplx s bttr thn cmplctd.
Flt s bttr thn nstd.

Lambda function can also be used as a filter. Following program use lambda function that filters all vowels from given string.

string='''
Beautiful is better than ugly.
Explicit is better than implicit.
Simple is better than complex.
Complex is better than complicated.
Flat is better than nested.
'''
consonants=list(filter(lambda x: x not in ['a','e','i','o','u'],string))
print (''.join(consonants))

reduce() function

Unlike map and filter functions, reduce() is not a built-in function, but is defined in built-in functools module. It also needs two arguments, a function and an iterable. However it returns a single value. The argument function is applied to two successive items in the list from left to right. Result of the function in first call becomes first argument and third item in list becomes second. Cumulative result is the return value of reduce() function.

In the example below, add() function is defined to return addition of two numbers. This function is used in reduce() function along with a range of numbers between 0 to 100. Output is sum of first 100 numbers.

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

num=functools.reduce(add, range(101))
print ('sum of first 100 numbers ',num)

Output:

sum of first 100 numbers  5050

We can use a lambda function instead of user-defined add() function for the same output.

num=functools.reduce(lambda x,y:x+y, range(101))

The functool module of Python's standard library consists of more first order functions which act on or return other function.

Leave a Reply

Your email address will not be published. Required fields are marked *

Comments

Eula

This is my first time here. I am truly impressed to read all this in one place.

Jaypee Dela Cruz

Thank you for your wonderful codes and website, you helped me a lot especially in this socket module. Thank you again!

lucky verma

Thank you for taking the time to share your knowledge about using python to find the path! Your insight and guidance is greatly appreciated.

Pre Engineered Metal Building

Usually I by no means touch upon blogs however your article is so convincing that I by no means prevent myself to mention it here.

Pre Engineered Metal Building

Usually, I never touch upon blogs; however, your article is so convincing that I could not prevent myself from mentioning how nice it is written.

Suggested Tutorials

Swift Tutorial

Introduction to Swift Tutorial
Swift Tutorial

Introduction to Swift Tutorial

Read More

R Programming Tutorial

R Programming

C# Tutorial

C# is an object-oriented programming developed by Microsoft that uses the .Net Framework. It utilizes the Common Language Interface (CLI) that describes the executable code as well as the runtime environment. C# can be used for various applications such as web applications, distributed applications, database applications, window applications etc.For greater understanding of this tutorial, a basic knowledge of object-oriented languages such as C++, Java etc. would be beneficial.
C# Tutorial

C# is an object-oriented programming developed by Microsoft that uses ...

Read More