Function is a set of organized lines of code that performs a specific, well defined task.
It is used reduce the number of lines of code and improve reusability.
Syntax:
def function_name(parameters): # function definition
Statements
return value(s)
...
...
function_name(parameters) # Caller
return
Returns back a value as specified. It marks the end of a function
A fruitful function is a function that returns a value
IN [1]
# Example 1:
def add(a, b): # Function Definition
return a + b # returns the sum
x = int(input())
y = int(input())
print(add(x, y)) # Function Calling
# Input:
# 12
# 13
stdin
12
13
stdout
25
Like variables, python functions should also be in lower_snake_case
One of the more universal, yet simple rules is: Function names should be verbs if the function changes the state of the program, and nouns if they’re used to return a certain value.
get_name()
will tell the developer what it returns as well as set_address(), is_male(), etc.get_number_of_pages_in_the_book()
is not good, something like get_book_page_count()
is better.get_name()
, set_name()
, etc.The most important thing to note is to follow a constant naming convention throughout the function
One liner of a function. It is created for use at one point or one statememt and is not intended to be named and stored.
Syntax:
lambda parameters: Statement
IN [9]
# Example 1
def is_even(x):
return x % 2 == 0 # One line function to check if even
a = int(input())
print("From is_even(x):", is_even(a))
print("From lambda:", (lambda x: x % 2 == 0)(a)) # Equivalent lambda function
# Input: 10
stdin
10
stdout
From is_even(x): True
From lambda: True
The lambda
function is generally created for use with iterables where the function is applied to several values but at only once (that part of the code).
The usual places include maps, filter and keys for sorting for any iterable. Visit Lists or Tuples to know more on them
Recursion is a method of solving a problem where the solution depends on solutions to smaller instances of the same problem.
A function that performs recursion.
A recursive function calls itself repeatedly by dividing the problem into sub problems until the solution is obtained for the smallest sub-problem.
def function(paramters1):
function(parameters2) # Recursive calling
IN [14]
# Example using factorial (n! = 1 * 2 * 3 ... n) n! = n * (n-1)!
def factorial(n):
if -1<n<=1: return 1 # End of recursion
else: return n * factorial(n-1) # recursive calling
n = int(input())
print(factorial(n))
# Input: 6
stdin
6
stdout
720
Breaking down of problem:
n = 6
n <= 1 False
6 * factorial(5)
n = 5
n <= 1 False
5 * factorial(4)
n = 4
n <= 1 False
4 * factorial(3)
n = 3
n <= 1 False
3 * factorial(2)
n = 2
n <= 1 False
2 * factorial(1)
n = 1
n <= 1 (n==1) True
1
Building up:
1
2 * 1
3 * 2 * 1
4 * 3 * 2 * 1
5 * 4 * 3 * 2 * 1
6 * 5 * 4 * 3 * 2 * 1
720
You can find the steps in recursion below
The ‘|’ line indicates the same level of recursive call
IN [5]
# The indent paramter defines the offset of output. This program is to understand recursion only.
def fact(n, indent=''):
print(indent, n, sep='')
if 0 <= n <= 1: return 1
else:
fac = n * fact(n-1, indent + "|\t")
print(indent, fac, sep='')
return fac
fact(6)
stdout
6
| 5
| | 4
| | | 3
| | | | 2
| | | | | 1
| | | | 2
| | | 6
| | 24
| 120
720
Values passed into a function. They are optional
Positional Arguments.
These are arguments required to execute a function.
The number of required arguments should be equal to the number of arguments passed.
If not, it will result in error.
IN [29]
# Example
def add(a, b): # Function Definition - no. of required arguments
return a+b # returns the sum
x = int(input())
y = int(input())
print(add(x, y)) # Function Calling - no. of args passed
# Input:
# 12
# 23
stdin
12
23
stdout
35
IN [30]
#Example
# Example
def add(a, b): # Function Definition - no. of required arguments
return a+b # returns the sum
x = int(input())
y = int(input())
print(add(x)) # Function Calling - no. of args passed < no. of required args
stdin
10
23
Error
Traceback (most recent call last):
File "D:\Programming\Python\Jupyter Notebooks\Python_Programming_Notes\temp.py", line 7, in <module>
print(add(x)) # Function Calling - no. of args passed < no. of required args
TypeError: add() missing 1 required positional argument: 'b'
These arguments are not positional but are required.
IN [20]
# Example 2
def add(a, b): # Function Definition - Parameters
print(a, b)
return a+b # returns the sum
x = int(input())
y = int(input())
print(add(b = x, a = y)) # Function Calling - Keywords are names of params used in definition
# Input: 10
# 23
stdin
10
23
stdout
23 10
33
Arguments which are optional. They have values by default.
IN [31]
#Example
def add(a, b = 0): # Function Definition - b is default args
print(a, b)
return a+b # returns the sum
x = int(input())
y = int(input())
# b given in function call
print('B given')
print(add(x, y)) # Function Calling
print()
# b not given in function call
print('B not given default = 0')
print(add(x)) # Function Calling
# Input: 12
# 23
stdin
12
23
stdout
B given
12 23
35
B not given default = 0
12 0
12
From python 3.8, ‘/’ is used to Separate positional args from non positional.
IN [32]
# Example
def add(a, /, b=0): # Function Definition
return a+b # returns the sum
x = int(input())
y = int(input())
print(add(x)) # Function Calling
# Input: 10
# 23
stdin
10
23
stdout
10
Args that are used when the number of arguments is not known. The arguments passed are stored as a tuple. The arguments that start with ‘ * ‘ indicate Variable length arguments and are called gather
IN [2]
#Example
# Example
def add(a, *b): # Function Definition - * indicates variable length arguments
print(b)
return a + sum(b) # returns the sum; sum is a built in function that returns sum of elements in an iterable
x = int(input())
y = int(input())
# 2 arguments
print(add(x, y))
print()
# 3 args
print(add(x, y, 10))
print()
# 4 args
print(add(x, y, 10, 20)) # Function Calling - no. of args passed
# Input: 10
# 23
stdin
10
23
stdout
(23,)
33
(23, 10)
43
(23, 10, 20)
63
Variable length arguements that are most commonly used. Stores the values as tuple
Variable length arguments of the form key = value. Stores the values as key-value mapping or dictionary.
IN [3]
#kwargs example
def kwargs_ex(**a):
print(a)
for k, v in a.items():
print(f"{k} = {v}")
kwargs_ex(x=2, y=3)
stdout
{'x': 2, 'y': 3}
x = 2
y = 3
The part of code where a variable can be accessed. Scopes: 1. Global Variable 2. Local Variable
Variable that can be acessed in any part of the program.
Variable that can be accessed only inside a specific block or part of a program.
IN [7]
#Example
def add(a, b):
c = a+b
print(c)
#return a+b
def printf():
print(k)
x = int(input('x:'))
y = int(input('y:'))
add(x,y)
print('Hello')
s = 10
z = -100
for i in range(5):
k = 'Hello'
print(k)
print(x,y,s,z)
printf()
print(k)
print(i)
print(c)
# Input:
# 10
# 23
stdin
x: 10
y: 23
stdout
33
Hello
Hello
Hello
Hello
Hello
Hello
10 23 10 -100
Hello
Hello
4
Error
x:
Traceback (most recent call last):
File "D:\Programming\Python\Jupyter Notebooks\Python_Programming_Notes\temp.py", line 10, in <module>
x = int(input('x:'))
ValueError: invalid literal for int() with base 10: 'x: 10'
IN [9]
def printf(): # Function definition
global k
k = 'Hi' #Local Variable Gloablized
print(k)
for i in range(5):
k = 'Hello' # Global Variable
print(k)
printf()
print(k)
stdout
Hello
Hello
Hello
Hello
Hello
Hi
Hi
Docstrings are most commonly used in a function. They act as descriptor of function, i.e., they describe the function.
Calling docstings:
function_name.__doc__
IN [1]
def fn():
'''This is a docstring'''
print(fn.__doc__) # Calls docstring
stdout
This is a docstring
Recursion involves calling function repeatedly to breakdown a problem.
Iteration is solving the problem by breaking down using loops.
Recursion is a easy way to solve a problem. But it is a bit time consuming. Iteration is hard coding but is efficient in solving the problems.
This brings in a new programming stream called Dynamic Programming.
Syntax:
print(values, end="\n", sep" ")
IN [3]
print(1,2,3, sep = "") # no separation between the values
stdout
123
IN [4]
print(1,2,3)
stdout
1 2 3
IN [5]
print(1,2,3, sep = '\t')
stdout
1 2 3
IN [6]
print(1,2,3)
print(4,5)
stdout
1 2 3
4 5
IN [7]
print(1,2,3, end='')# end of print is <none>
print(4,5)
stdout
1 2 34 5
IN [8]
print(1,2,3, end=' ') # end of print is <space>
print(4,5)
stdout
1 2 3 4 5
Syntax:
input(prompt="")
IN [10]
n = input()
# Input: 20
stdin
20
IN [11]
a = input(prompt = 'Prompt')
# Input: 10
stdin
Prompt 10
Syntax:
int(x, base = 10)
IN [13]
int('10')
IN [14]
b = '110'
int(b, 2)
IN [15]
x = '7af'
int(x, 16)
IN [17]
o = '75'
int(o, 8)
Syntax:
float(x = 0)
IN [20]
float()
IN [21]
float ('1.2')
IN [22]
float(1)
IN [24]
float('12')
Python does not allows multiple functions with different parameters with same name. If so exist, the last function definition replaces the first.
IN [25]
def fn():
return 'Hi'
def fn(x,y):
return x+y
print(fn())
print(fn(10, 5))
Error
Traceback (most recent call last):
File "D:\Programming\Python\Jupyter Notebooks\Python_Programming_Notes\temp.py", line 5, in <module>
print(fn())
TypeError: fn() missing 2 required positional arguments: 'x' and 'y'
Argument given to var. args are gathered and stored together to form a tuple. This is called gather.
Argument given as a list/tuple is split across required variable. This is called scatter
IN [2]
#Example
def add(a, *b): # Function Definition
print(a, b)
return a + sum(b) # returns the sum; sum is a built in function that returns sum of elements in an iterable
l = list(map(int, input().split()))
print(add(*l)) # Function Calling
# Input: 10
# 23
# 30
# 40
stdin
10 23 30 40
stdout
10 (23, 30, 40)
103
A function returning another function is called a higher order function
def function1(params):
def function2(params):
Statements
return function2
IN [13]
def deco(k): # Higher order function / decorator
def multiple(n):
return n*k
return multiple
second_multiple = deco(2)
n = int(input("Enter a num\n"))
print(second_multiple(n))
stdin
Enter a num
6
stdout
12