For efficiently programming with Python, we need to learn how to write functions. In this article we will be familiar with basic of function programming in Python 3 and learn about some Python’s built-in functions through several examples. As a prerequisite for this tutorial, it is better to learn the following first:
The following is a good resource to learn more about function programming subject:
We can use Python to define any function that we want. A function should include:
- name, to be able to refer it later
- documentation, to explain the function (optional)
- parameters, that could be zero or more
- body, that contains all computations that the function is doing
In general, we can use def command to define functions like:
defname(par1, par2, par3, ...):
"Documentation."bodyreturnresultFor example:
defmult(a, b):
"Two numbers multiplication."m=a*breturnmmult(12, 13)
## 156In general, we can define three types of functions:
- computative, find the results by substituting parameters and doing calculations
- iterative, find the results by iteration (control flow tools)
- recursive, find the results by recursion (function itself)
In above example, we used a computative function to find a * b. Now let’s use iterative method:
defmult_itr(a, b):
""" Two integers multiplication by iteration. Note that a * b is equal to a + a + ... + a; b times. """result=0whileb>0:
result+=ab-=1returnresultmult_itr(12, 13)
## 156We can also use recursive method such that:
defmult_rec(a, b):
""" Two integers multiplication by recursion. Note that a * b is equal to a + a(b-1). """ifb==1:
returnaelse:
returna+mult_rec(a,b-1)
mult_rec(12, 13)
## 156At each iteration, both iterative and recursive functions follow this pattern to find 12 * 13:
1212+1212+12+12
...
12+12+ ... +12 (13times)For another example let’s compute an integer factorial with all mentioned methods:
deffact(n):
"Compute n factorial by using Python math library"importmathreturnmath.factorial(n)
fact(6)
## 720deffact_itr(n):
""" Compute n factorial by iteration. Note that n! is equal to n(n-1)(n-2)...1. """result=1whilen>1:
result*=nn-=1returnresultfact_itr(6)
## 720deffact_rec(n):
""" Compute n factorial by recursion. Note that n! is equal to n(n-1)!. """ifn==1:
returnnelse:
returnn*fact_rec(n-1)
fact_rec(6)
## 720Each of the above method has their pros and cons. For instance, let’s try a function that returns numbers in Fibonacci series:
deffib(n):
""" Function to return nth Fibonacci number. By using Binet's Fibonacci number formula. """phi=5**0.5ifn<2:
returnnelse:
return ((1+phi)**n- (1-phi)**n)/(2**n*phi)
[fib(x) forxinrange(12)]
## [0, 1, 1.0, 2.0, 3.0000000000000004, 5.000000000000001, 8.000000000000002, 13.000000000000002, 21.000000000000004, 34.00000000000001, 55.000000000000014, 89.00000000000003]deffib_itr(n):
""" Iterative function to return nth Fibonacci number. Note that Fibonacci series is 0, 1, 0+1=1, 1+1=2, 1+2=3, 2+3=5, ... . """series= []
a, b=0, 1whilelen(series) <n:
series.append(a)
a, b=b, a+breturna
[fib_itr(x) forxinrange(12)]
## [0, 1, 1, 2, 3, 5, 8, 13, 21, 34, 55, 89]deffib_rec(n):
""" Inefficient recursive function to return nth Fibonacci number. Note that Fibonacci series is f(n-2) + f(n-1). """ifn<2:
returnnelse:
returnfib_rec(n-2) +fib_rec(n-1)
[fib_rec(x) forxinrange(12)]
## [0, 1, 1, 2, 3, 5, 8, 13, 21, 34, 55, 89]Here, computative method provides an estimation (which is actually a
very good estimation) of the Fibonacci number and recursive method
requires a lot of time as n gets bigger since at each iteration it
needs to compute two fib_rec such that (for n = 5):
fib_rec(5)
_______|________||fib_rec(4) fib_rec(3)
___|______|___||||fib(3) fib(2) fib(2) 1__|____|____|__||||||fib(2) 11010__|__||10Therefore, it is very important to always choose the right approach based on the function context.
Python provides another method that let us to write functions in a very compact way that called lambda function.
Python includes a quick one-line construction of functions that is often convenient to make your code compact. In general we can write lambda function such that:
name=lambdapar1, par2, par3, ...: bodyFor example:
cube=lambdax: x**3cube(2)
## 8Which is same as:
defcube(x):
returnx**3cube(2)
## 8For another example, let’s find Euclidean norm of a vector by a lambda function:
pnorm=lambdav, p=2: sum([abs(x)**pforxinv])**(1/p)
## Examplev= [2,3,4]
pnorm(v)
## 5.385164807134504pnorm(v,1)
## 9.0Or for instance, let’s replace an string in a mathematical formula with a number and find the answer:
re=lambdaf, x, z: eval(f.replace(str(x), str(z)))
## Examplef='2*x + 5're(f,'x',2)
## 9For last example in here, let’s define single limit formula to find the second derivative of f(x) = x^3 for x = 2 by using lambda:
defderiv2nd(f, x, h=1E-6):
"Single limit formula."return (f(x-h) -2*f(x) +f(x+h))/float(h**2) f=lambdax: x**3deriv2nd(f, 2)
## 12.002843163827492As we know, the second derivative of f(x) = x^3 is equal to 6 * x
which is equal to 12 for x = 2. Note that we can find the derivative
of functions by using SymPy package, for example:
importsympyx=sympy.symbols('x')
f=x**3ff=f.diff(x,2)
ff## 6*xff.subs({x:2})
## 12Map and filter are two Python built-in functions that let us to expand our function programming tools. In general, map function is:
map(function, iterable, ...)When a function, that could be another built-in function or a created function by def or lambda, applies on each element of an iterable (i.e. lists, tuples or dictionaries - see here to learn more). For an example let’s assume we have sales rate for each month during each season of a year and are interested to know what is the total seasonal sales:
sale= [(1,3,4,5),(3,4,5,6),(7,6,5,5),(8,6,9,1)]
seasonal=list(map(sum, sale))
seasonal## [13, 18, 23, 24]We can answer the above question without using map by:
sale= [(1,3,4,5),(3,4,5,6),(7,6,5,5),(8,6,9,1)]
seasonal= []
foriinsale:
seasonal.append(sum(i))
seasonal## [13, 18, 23, 24]As you can see, without map we need a loop to address each element of the iterable.
For another example, let’s assume we have an iterable of strings (e.g. a list of names) and want them to be in lowercase:
fruit= ['APPLE','ORANGE','PEACH','BANANA']
list(map(str.lower, fruit))
## ['apple', 'orange', 'peach', 'banana']Or we can use map to round a list of float numbers:
flt= [2.0678,3.9870,4.7869,5.3459]
list(map(round, flt, [2]*len(flt)))
## [2.07, 3.99, 4.79, 5.35]Note that the above function has two iterables (flt and
[2,2,2,2]).
We can also use map to create new functions. For instance, let’s
define zip_diy function that do same operation as Python zip
function:
defzip_diy(x,y):
returnmap(lambdaa, b: (a,b), x, y)
## Examplelist_1= [1,2,3]
list_2= [3,2,1]
list(zip_diy(list_1, list_2))
## [(1, 3), (2, 2), (3, 1)]list(zip(list_1, list_2))
## [(1, 3), (2, 2), (3, 1)]As you noticed, map in zip_diy includes a lambda function that
generates (a,b) tuple for each element in given iterables, x and
y.
Filter is another important tool in function programming. As you probably guessed, filter lets us to filter an iterable. In general, filter function is:
filter(function, iterable)When the function is required to return a boolean type (True/False)
by testing each element of the iterable. For an example let’s select
numbers greater than 22 in a list in below:
number= [88,22,11,33,2,99]
list(filter(lambdax: x>22, number))
## [88, 33, 99]Traditionally we can use for loop and if condition to filter the
list such that:
number= [88,22,11,33,2,99]
select= []
foriinnumber:
ifi>22:
select.append(i)
select## [88, 33, 99]## Or
[iforiinnumberifi>22]
## [88, 33, 99]Now let’s define a function to return numbers (integer, float and complex) from a list of numbers and strings:
defreturn_num(lis):
returnfilter(lambdax: isinstance(x, (int,float,complex)), lis) ## Exampletest= [2.05, 3, 'aaa', 4.23, 'bbb', 7j]
list(return_num(test))
## [2.05, 3, 4.23, 7j]Copyright, Ashkan Mirzaee | Content is available under CC BY-SA 3.0 | Sourcecode licensed under GPL-3.0