0% found this document useful (0 votes)
41 views27 pages

Chapter 2

Python

Uploaded by

archanasarangi5
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as DOCX, PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
41 views27 pages

Chapter 2

Python

Uploaded by

archanasarangi5
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as DOCX, PDF, TXT or read online on Scribd
You are on page 1/ 27

Chapter-4

Python Functions



Python Functions is a block of statements that return the specific
task. The idea is to put some commonly or repeatedly done tasks
together and make a function so that instead of writing the same
code again and again for different inputs, we can do the function
calls to reuse code contained in it over and over again.
Some Benefits of Using Functions
 Increase Code Readability
 Increase Code Reusability
Python Function Declaration
The syntax to declare a function is:

Syntax of Python Function Declaration

Types of Functions in Python


There are mainly two types of functions in Python.
 Built-in library function: These are Standard functions in
Python that are available to use.
 User-defined function: We can create our own functions
based on our requirements.
Creating a Function in Python
We can define a function in Python, using the def keyword. We can
add any type of functionalities and properties to it as we require.
 Python3

# A simple Python function

def fun():
print("Welcome to GFG")

Calling a Python Function


After creating a function in Python we can call it by using the name
of the function followed by parenthesis containing parameters of
that particular function.
 Python3

# A simple Python function


def fun():
print("Welcome to GFG")

# Driver code to call a function


fun()

Output:
Welcome to GFG
Python Function with Parameters
If you have experience in C/C++ or Java then you must be thinking
about the return type of the function and data type of arguments.
That is possible in Python as well (specifically for Python 3.5 and
above).
Defining and calling a function with parameters
def function_name(parameter: data_type) -> return_type:
"""Docstring"""
# body of the function
return expression
The following example uses arguments and parameters that you will
learn later in this article so you can come back to it again if not
understood.
 Python3

def add(num1: int, num2: int) -> int:


"""Add two numbers"""
num3 = num1 + num2

return num3

# Driver code
num1, num2 = 5, 15
ans = add(num1, num2)
print(f"The addition of {num1} and {num2} results {ans}.")

Output:
The addition of 5 and 15 results 20.
Note: The following examples are defined using syntax 1, try to
convert them in syntax 2 for practice.
 Python3

# some more functions


def is_prime(n):
if n in [2, 3]:
return True
if (n == 1) or (n % 2 == 0):
return False
r = 3
while r * r <= n:
if n % r == 0:
return False
r += 2
return True
print(is_prime(78), is_prime(79))

Output:
False True
Python Function Arguments
Arguments are the values passed inside the parenthesis of the
function. A function can have any number of arguments separated
by a comma.
In this example, we will create a simple function in Python to check
whether the number passed as an argument to the function is even
or odd.
 Python3

# A simple Python function to check


# whether x is even or odd
def evenOdd(x):
if (x % 2 == 0):
print("even")
else:
print("odd")

# Driver code to call the function


evenOdd(2)
evenOdd(3)

Output:
even
odd
Types of Python Function Arguments
Python supports various types of arguments that can be passed at
the time of the function call. In Python, we have the following 4
types of function arguments.
 Default argument
 Keyword arguments (named arguments)
 Positional arguments
 Arbitrary arguments (variable-length arguments *args
and **kwargs)
Let’s discuss each type in detail.
Default Arguments
A default argument is a parameter that assumes a default value if a
value is not provided in the function call for that argument. The
following example illustrates Default arguments.
 Python3

# Python program to demonstrate


# default arguments
def myFun(x, y=50):
print("x: ", x)
print("y: ", y)

# Driver code (We call myFun() with only


# argument)
myFun(10)

Output:
x: 10
y: 50
Like C++ default arguments, any number of arguments in a function
can have a default value. But once we have a default argument, all
the arguments to its right must also have default values.
Keyword Arguments
The idea is to allow the caller to specify the argument name with
values so that the caller does not need to remember the order of
parameters.
 Python3

# Python program to demonstrate Keyword Arguments


def student(firstname, lastname):
print(firstname, lastname)
# Keyword arguments
student(firstname='Geeks', lastname='Practice')
student(lastname='Practice', firstname='Geeks')

Output:
Geeks Practice
Geeks Practice
Positional Arguments
We used the Position argument during the function call so that the
first argument (or value) is assigned to name and the second
argument (or value) is assigned to age. By changing the position, or
if you forget the order of the positions, the values can be used in the
wrong places, as shown in the Case-2 example below, where 27 is
assigned to the name and Suraj is assigned to the age.
 Python3

def nameAge(name, age):


print("Hi, I am", name)
print("My age is ", age)

# You will get correct output because


# argument is given in order
print("Case-1:")
nameAge("Suraj", 27)
# You will get incorrect output because
# argument is not in order
print("\nCase-2:")
nameAge(27, "Suraj")

Output:
Case-1:
Hi, I am Suraj
My age is 27
Case-2:
Hi, I am 27
My age is Suraj
Arbitrary Keyword Arguments
In Python Arbitrary Keyword Arguments, *args, and **kwargs can
pass a variable number of arguments to a function using special
symbols. There are two special symbols:
 *args in Python (Non-Keyword Arguments)
 **kwargs in Python (Keyword Arguments)
Example 1: Variable length non-keywords argument
 Python3

# Python program to illustrate


# *args for variable number of arguments
def myFun(*argv):
for arg in argv:
print(arg)

myFun('Hello', 'Welcome', 'to', 'GeeksforGeeks')

Output:
Hello
Welcome
to
GeeksforGeeks
Example 2: Variable length keyword arguments
 Python3

# Python program to illustrate


# *kwargs for variable number of keyword arguments

def myFun(**kwargs):
for key, value in kwargs.items():
print("%s == %s" % (key, value))

# Driver code
myFun(first='Geeks', mid='for', last='Geeks')

Output:
first == Geeks
mid == for
last == Geeks
Docstring
The first string after the function is called the Document string
or Docstring in short. This is used to describe the functionality of the
function. The use of docstring in functions is optional but it is
considered a good practice.
The below syntax can be used to print out the docstring of a
function:
Syntax: print(function_name.__doc__)
Example: Adding Docstring to the function
 Python3

# A simple Python function to check


# whether x is even or odd

def evenOdd(x):
"""Function to check if the number is even or odd"""

if (x % 2 == 0):
print("even")
else:
print("odd")

# Driver code to call the function


print(evenOdd.__doc__)

Output:
Function to check if the number is even or odd
Python Function within Functions
A function that is defined inside another function is known as
the inner function or nested function. Nested functions can
access variables of the enclosing scope. Inner functions are used so
that they can be protected from everything happening outside the
function.
 Python3

# Python program to
# demonstrate accessing of
# variables of nested functions

def f1():
s = 'I love GeeksforGeeks'

def f2():
print(s)

f2()

# Driver's code
f1()

Output:
I love GeeksforGeeks
Anonymous Functions in Python
In Python, an anonymous function means that a function is without a
name. As we already know the def keyword is used to define the
normal functions and the lambda keyword is used to create
anonymous functions.
 Python3

# Python code to illustrate the cube of a number


# using lambda function
def cube(x): return x*x*x

cube_v2 = lambda x : x*x*x

print(cube(7))
print(cube_v2(7))

Output:
343
343
Recursive Functions in Python
Recursion in Python refers to when a function calls itself. There are
many instances when you have to build a recursive function to
solve Mathematical and Recursive Problems.
Using a recursive function should be done with caution, as a
recursive function can become like a non-terminating loop. It is
better to check your exit statement while creating a recursive
function.
 Python3

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

print(factorial(4))

Output
24
Here we have created a recursive function to calculate the factorial
of the number. You can see the end statement for this function is
when n is equal to 0.
Return Statement in Python Function
The function return statement is used to exit from a function and go
back to the function caller and return the specified value or data
item to the caller. The syntax for the return statement is:
return [expression_list]
The return statement can consist of a variable, an expression, or a
constant which is returned at the end of the function execution. If
none of the above is present with the return statement a None
object is returned.
Example: Python Function Return Statement
 Python3

def square_value(num):
"""This function returns the square
value of the entered number"""
return num**2

print(square_value(2))
print(square_value(-4))

Output:
4
16
Pass by Reference and Pass by Value
One important thing to note is, in Python every variable name is a
reference. When we pass a variable to a function, a new reference
to the object is created. Parameter passing in Python is the same as
reference passing in Java.
 Python3

# Here x is a new reference to same list lst


def myFun(x):
x[0] = 20

# Driver Code (Note that lst is modified


# after function call.
lst = [10, 11, 12, 13, 14, 15]
myFun(lst)
print(lst)

Output:
[20, 11, 12, 13, 14, 15]
When we pass a reference and change the received reference to
something else, the connection between the passed and received
parameters is broken. For example, consider the below program as
follows:
 Python3

def myFun(x):

# After below line link of x with previous


# object gets broken. A new object is assigned
# to x.
x = [20, 30, 40]

# Driver Code (Note that lst is not modified


# after function call.
lst = [10, 11, 12, 13, 14, 15]
myFun(lst)
print(lst)

Output:
[10, 11, 12, 13, 14, 15]
Another example demonstrates that the reference link is broken if
we assign a new value (inside the function).
 Python3

def myFun(x):

# After below line link of x with previous


# object gets broken. A new object is assigned
# to x.
x = 20

# Driver Code (Note that x is not modified


# after function call.
x = 10
myFun(x)
print(x)

Output:
10
Exercise: Try to guess the output of the following code.
 Python3

def swap(x, y):


temp = x
x = y
y = temp

# Driver code
x = 2
y = 3
swap(x, y)
print(x)
print(y)

Output:
2
3
Iterators in Python



An iterator in Python is an object that is used to iterate over iterable
objects like lists, tuples, dicts, and sets. The Python iterators object
is initialized using the iter() method. It uses the next() method for
iteration.
1. __iter__(): The iter() method is called for the initialization of
an iterator. This returns an iterator object
2. __next__(): The next method returns the next value for the
iterable. When we use a for loop to traverse any iterable
object, internally it uses the iter() method to get an iterator
object, which further uses the next() method to iterate over.
This method raises a StopIteration to signal the end of the
iteration.
Python iter() Example
 Python3
string = "GFG"
ch_iterator = iter(string)

print(next(ch_iterator))
print(next(ch_iterator))
print(next(ch_iterator))

Output :
G
F
G

Creating and looping over an iterator using iter() and


next()

Below is a simple Python Iterator that creates an iterator type that


iterates from 10 to a given limit. For example, if the limit is 15, then
it prints 10 11 12 13 14 15. And if the limit is 5, then it prints
nothing.

 Python3

# A simple Python program to demonstrate


# working of iterators using an example type
# that iterates from 10 to given value

# An iterable user defined type


class Test:

# Constructor
def __init__(self, limit):
self.limit = limit

# Creates iterator object


# Called when iteration is initialized
def __iter__(self):
self.x = 10
return self

# To move to next element. In Python 3,


# we should replace next with __next__
def __next__(self):
# Store current value ofx
x = self.x

# Stop iteration if limit is reached


if x > self.limit:
raise StopIteration

# Else increment and return old value


self.x = x + 1;
return x

# Prints numbers from 10 to 15


for i in Test(15):
print(i)

# Prints nothing
for i in Test(5):
print(i)

Output:
10
11
12
13
14
15

Iterating over built-in iterable using iter() method

In the following iterations, the iteration state and iterator variable is


managed internally (we can’t see it) using an iterator object to
traverse over the built-in iterable like list, tuple, dict, etc.
 Python3

# Sample built-in iterators

# Iterating over a list


print("List Iteration")
l = ["geeks", "for", "geeks"]
for i in l:
print(i)

# Iterating over a tuple (immutable)


print("\nTuple Iteration")
t = ("geeks", "for", "geeks")
for i in t:
print(i)

# Iterating over a String


print("\nString Iteration")
s = "Geeks"
for i in s :
print(i)

# Iterating over dictionary


print("\nDictionary Iteration")
d = dict()
d['xyz'] = 123
d['abc'] = 345
for i in d :
print("%s %d" %(i, d[i]))

Output:
List Iteration
geeks
for
geeks

Tuple Iteration
geeks
for
geeks

String Iteration
G
e
e
k
s
Dictionary Iteration
xyz 123
abc 345

Iterable vs Iterator
Python iterable and Python iterator are different. The main
difference between them is, iterable in Python cannot save the state
of the iteration, whereas in iterators the state of the current iteration
gets saved.
Note: Every iterator is also an iterable, but not every iterable is an
iterator in Python.
Read more – Difference between iterable and iterator.

Iterating on an Iterable

Iterating on each item of the iterable.

 Python3

tup = ('a', 'b', 'c', 'd', 'e')

for item in tup:


print(item)

Output:
a
b
c
d
e

Iterating on an iterator

 Python3

tup = ('a', 'b', 'c', 'd', 'e')

# creating an iterator from the tuple


tup_iter = iter(tup)
print("Inside loop:")
# iterating on each item of the iterator object
for index, item in enumerate(tup_iter):
print(item)

# break outside loop after iterating on 3 elements


if index == 2:
break

# we can print the remaining items to be iterated using next()


# thus, the state was saved
print("Outside loop:")
print(next(tup_iter))
print(next(tup_iter))

Output:
Inside loop:
a
b
c
Outside loop:
D,e

enerators in Python



A Generator in Python is a function that returns an iterator using the
Yield keyword. In this article, we will discuss how the generator
function works in Python.
Generator Function in Python
A generator function in Python is defined like a normal function, but
whenever it needs to generate a value, it does so with the yield
keyword rather than return. If the body of a def contains yield, the
function automatically becomes a Python generator function.
Create a Generator in Python
In Python, we can create a generator function by simply using the
def keyword and the yield keyword. The generator has the following
syntax in Python:
def function_name():
yield statement
Example:
In this example, we will create a simple generator that will yield
three integers. Then we will print these integers by using Python for
loop.
 Python3

# A generator function that yields 1 for first time,


# 2 second time and 3 third time
def simpleGeneratorFun():
yield 1
yield 2
yield 3

# Driver code to check above generator function


for value in simpleGeneratorFun():
print(value)

Output:
1
2
3

Generator Object
Python Generator functions return a generator object that is
iterable, i.e., can be used as an Iterator. Generator objects are used
either by calling the next method of the generator object or using
the generator object in a “for in” loop.
Example:
In this example, we will create a simple generator function in Python
to generate objects using the next() function.
 Python3

# A Python program to demonstrate use of


# generator object with next()

# A generator function
def simpleGeneratorFun():
yield 1
yield 2
yield 3

# x is a generator object
x = simpleGeneratorFun()
# Iterating over the generator object using next

# In Python 3, __next__()
print(next(x))
print(next(x))
print(next(x))

Output:
1
2
3

Example:
In this example, we will create two generators for Fibonacci
Numbers, first a simple generator and second generator using a for
loop.
 Python3

# A simple generator for Fibonacci Numbers


def fib(limit):

# Initialize first two Fibonacci Numbers


a, b = 0, 1

# One by one yield next Fibonacci Number


while a < limit:
yield a
a, b = b, a + b

# Create a generator object


x = fib(5)

# Iterating over the generator object using next


# In Python 3, __next__()
print(next(x))
print(next(x))
print(next(x))
print(next(x))
print(next(x))

# Iterating over the generator object using for


# in loop.
print("\nUsing for in loop")
for i in fib(5):
print(i)

Output:
0
1
1
2
3

Using for in loop


0
1
1
2
3

Python Generator Expression


In Python, generator expression is another way of writing the
generator function. It uses the Python list comprehension technique
but instead of storing the elements in a list in memory, it creates
generator objects.
Generator Expression Syntax
The generator expression in Python has the following Syntax:
(expression for item in iterable)
Example:
In this example, we will create a generator object that will print the
multiples of 5 between the range of 0 to 5 which are also divisible by
2.
 Python3

# generator expression
generator_exp = (i * 5 for i in range(5) if i%2==0)

for i in generator_exp:
print(i)

Output:
0
10
20
Recursion in Python



The term Recursion can be defined as the process of defining
something in terms of itself. In simple words, it is a process in which
a function calls itself directly or indirectly.

Advantages of using recursion


A complicated function can be split down into smaller sub-
problems utilizing recursion.
 Sequence creation is simpler through recursion than
utilizing any nested iteration.
 Recursive functions render the code look simple and
effective.
Disadvantages of using recursion
A lot of memory and time is taken through recursive calls
which makes it expensive for use.
 Recursive functions are challenging to debug.
 The reasoning behind recursion can sometimes be tough to
think through.
Syntax:
def func(): <--
|
| (recursive call)
|
func() ----
Example 1: A Fibonacci sequence is the integer sequence of 0, 1, 1,
2, 3, 5, 8….
 Python3

# Program to print the fibonacci series upto n_terms

# Recursive function
def recursive_fibonacci(n):
if n <= 1:
return n
else:
return(recursive_fibonacci(n-1) + recursive_fibonacci(n-2))

n_terms = 10

# check if the number of terms is valid


if n_terms <= 0:
print("Invalid input ! Please input a positive value")
else:
print("Fibonacci series:")
for i in range(n_terms):
print(recursive_fibonacci(i))

Output
Fibonacci series:
0
1
1
2
3
5
8
13
21
34
Example 2: The factorial of 6 is denoted as 6! = 1*2*3*4*5*6 =
720.
 Python3

# Program to print factorial of a number


# recursively.

# Recursive function
def recursive_factorial(n):
if n == 1:
return n
else:
return n * recursive_factorial(n-1)

# user input
num = 6

# check if the input is valid or not


if num < 0:
print("Invalid input ! Please enter a positive number.")
elif num == 0:
print("Factorial of number 0 is 1")
else:
print("Factorial of number", num, "=", recursive_factorial(num))

Output
Factorial of number 6 = 720

What is Tail-Recursion?
A unique type of recursion where the last procedure of a function is
a recursive call. The recursion may be automated away by
performing the request in the current stack frame and returning the
output instead of generating a new stack frame. The tail-recursion
may be optimized by the compiler which makes it better than non-
tail recursive functions.
Is it possible to optimize a program by making use of a tail-
recursive function instead of non-tail recursive function?
Considering the function given below in order to calculate the
factorial of n, we can observe that the function looks like a tail-
recursive at first but it is a non-tail-recursive function. If we observe
closely, we can see that the value returned by Recur_facto(n-1) is
used in Recur_facto(n), so the call to Recur_facto(n-1) is not the last
thing done by Recur_facto(n).
 Python3

# Program to calculate factorial of a number


# using a Non-Tail-Recursive function.

# non-tail recursive function


def Recur_facto(n):

if (n == 0):
return 1

return n * Recur_facto(n-1)

# print the result


print(Recur_facto(6))

Output
720
We can write the given function Recur_facto as a tail-recursive
function. The idea is to use one more argument and in the second
argument, we accommodate the value of the factorial. When n
reaches 0, return the final value of the factorial of the desired
number.

 Python3

# Program to calculate factorial of a number


# using a Tail-Recursive function.

# A tail recursive function


def Recur_facto(n, a = 1):

if (n == 0):
return a

return Recur_facto(n - 1, n * a)

# print the result


print(Recur_facto(6))

Output
720

Higher Order Functions in Python





A function is called Higher Order Function if it contains other
functions as a parameter or returns a function as an output i.e, the
functions that operate with another function are known as Higher
order Functions. It is worth knowing that this higher order function is
applicable for functions and methods as well that takes functions as
a parameter or returns a function as a result. Python too supports
the concepts of higher order functions. Properties of higher-order
functions:
 A function is an instance of the Object type.
 You can store the function in a variable.
 You can pass the function as a parameter to another
function.
 You can return the function from a function.
 You can store them in data structures such as hash tables,
lists, …
Functions as objects
In Python, a function can be assigned to a variable. This assignment
does not call the function, instead a reference to that function is
created. Consider the below example, for better
understanding. Example:

# Python program to illustrate functions


# can be treated as objects
def shout(text):
return text.upper()

print(shout('Hello'))

# Assigning function to a variable


yell = shout

print(yell('Hello'))

Output:
HELLO
HELLO
In the above example, a function object referenced by shout and
creates a second name pointing to it, yell.
Passing Function as an argument to other function
Functions are like objects in Python, therefore, they can be passed
as argument to other functions. Consider the below example, where
we have created a function greet which takes a function as an
argument. Example:

# Python program to illustrate functions


# can be passed as arguments to other functions
def shout(text):
return text.upper()

def whisper(text):
return text.lower()

def greet(func):
# storing the function in a variable
greeting = func("Hi, I am created by a function \
passed as an argument.")
print(greeting)
greet(shout)
greet(whisper)

Output:
HI, I AM CREATED BY A FUNCTION PASSED AS AN ARGUMENT.
hi, i am created by a function passed as an argument.
Returning function
As functions are objects, we can also return a function from another
function. In the below example, the create_adder function returns
adder function. Example:

# Python program to illustrate functions


# Functions can return another function

def create_adder(x):
def adder(y):
return x + y

return adder

add_15 = create_adder(15)

print(add_15(10))

Output:
25

Decorators
Decorators are the most common use of higher-order functions in
Python. It allows programmers to modify the behavior of function or
class. Decorators allow us to wrap another function in order to
extend the behavior of wrapped function, without permanently
modifying it. In Decorators, functions are taken as the argument into
another function and then called inside the wrapper
function. Syntax:
@gfg_decorator
def hello_decorator():
.
.
.
The above code is equivalent to –
def hello_decorator():
.
.
.

hello_decorator = gfg_decorator(hello_decorator)
In the above code, gfg_decorator is a callable function, will add some
code on the top of some another callable
function, hello_decorator function and return the wrapper
function. Example:

# defining a decorator
def hello_decorator(func):

# inner1 is a Wrapper function in


# which the argument is called

# inner function can access the outer local


# functions like in this case "func"
def inner1():
print("Hello, this is before function execution")

# calling the actual function now


# inside the wrapper function.
func()

print("This is after function execution")

return inner1

# defining a function, to be called inside wrapper


def function_to_be_used():
print("This is inside the function !!")

# passing 'function_to_be_used' inside the


# decorator to control its behavior
function_to_be_used = hello_decorator(function_to_be_used)

# calling the function


function_to_be_used()
Output:
Hello, this is before function execution
This is inside the function !!
This is after function execution

You might also like