Python Unit1(Chapter4 and 5)
Python Unit1(Chapter4 and 5)
Unit 1 Chapter 4
Exception Handling
Errors
Errors are problems that occur in the program due to an illegal operation performed by the user
or by the fault of a programmer, which halts the normal flow of the program. Errors are also
termed bugs or faults. There are mainly two types of errors in python programming.
1. Syntax errors
2. Logical Errors or Exceptions
Syntax Errors
A syntax error is one of the most basic types of error in programming. Whenever we do not
write the proper syntax of the python programming language (or any other language) then the
python interpreter throws an error known as a syntax error. The syntax error simply means
that the python interpreter is unable to understand a line of code.
Example:
number = 100
if number > 50
print("Number is greater than 50!")
Output:
File "test.py", line 3
if number > 50
^
SyntaxError: invalid syntax
Some of the general syntax errors can be typing errors (errors), incorrect indentation, or
incorrect arguments. In case of syntax errors, we should look at our code and try to understand
the problem.
Note: Syntax errors can also be called Compile Time Error. Some of the most common
compile-time errors are syntax errors, library references, incorrect import of library functions
and methods, uneven bracket pair(s), etc.
Note: In various IDEs (Integrated Development Environment), the syntax error(s) are shown
by red dashed lines.
Logical Errors
Logical Errors (Runtime errors) are those errors that cannot be caught during compilation
time. As we cannot check these errors during compile time, we name them Exceptions. Since
we cannot check thelogical errors during compilation time, it is difficult to find them. So, run-
time can cause some serious issues so we should handle them effectively.
❖ ZeroDivisionError Exception
ZeroDivisionError is raised by the Python interpreter when we try to divide any number by
zero.
Example:
number = 100
divided_by_zero = number / 0
print(divided_by_zero)
Output:
Traceback (most recent call last):
File "d:\test.py", line 2, in <module>
divided_by_zero = number / 0
ZeroDivisionError: division by zero
❖ Indentation error
The Indentation error is another type of error in python that can be summed up inside the syntax
error. As we know, we use indentation to define a block of code in python. So, in case of
improper indentation, the Python interpreter raises an Indentation error.
Example:
number = 57
if number == 57:
print(57)
Output:
File "d:\test.py", line 4
print(57)
^
IndentationError: expected an indented block
Exception
An exception is a class in Python that represents an error. When an exception is raised during
the execution of code, it disrupts the normal flow of the program and can lead to a halt state or
even a crash. To avoid this, it's important to do Exception handling in Python in a way that
allows the program to continue running even if an error occurs.
It's important to note that try and except blocks must be used together in order to handle
exceptions properly. Writing just try or except blocks alone will result in an error. In addition,
the except block can specify the type of exception that it wants to catch.
IndexError As the name suggests, the IndexError is raised when the wrong index of
a list is used.
AssertionError AssertionError is raised when the assert statement fails
AttributeError AttributeError is raised when an attribute assignment is failed.
ImportError ImportError is raised when an imported module is not found or there is a
problem in importing the required module.
KeyError KeyError is raised when the key of the dictionary is not found.
NameError NameError is raised when the variable is not yet defined.
MemoryError MemoryError is raised when a program runs out of memory.
TypeError TypeError is raised when a function or an operation is applied in an
incorrect type.
EOFError EOFError is raised when the input() function hits the condition of end-
of-file.
FloatingPointError FloatingPointError is raised when a floating-point operation fails.
In the above example, we caught the exception that was being raised in the try block, but the
except blocks are going to catch all the exceptions that try might raise.
Well, it’s considered a good practice to catch specific types of exceptions and handle them
accordingly. And yes, try can have multiple except blocks. We can also use a tuple of values
in an except to receive multiple specific exception types.
Example:
def divideNos(a, b):
return a/b
try:
a = input('enter a:')
b = input('enter b:')
print('after division', divideNos(a, b))
a = [1, 2, 3]
print(a[3])
except IndexError:
print('index error')
except ZeroDivisionError:
print('zero division error')
Output:
enter a:4
enter b:2
after division 2.0
index error
• In the above code the exceptions raised totally depend upon the input that the user might
enter. Hence if a user enters a value as 0 for ‘b’, the python interpreter will raise
a ZeroDivisionError.
• And as the array ‘a’ has a length of 3, and the user is trying to access an element at
index 3, an IndexError will be raised by the python interpreter.
• Each except block has been defined for both the exceptions as one of them receives
Example:
Where an exception is raised in the try block and except is triggered.
try:
temp = [1, 2, 3]
temp[4]
except Exception as e:
print('in exception block: ', e)
else:
print('in else block')
finally:
print('in finally block')
Output:
in exception block: list index out of range
in finally block
In the above code, we’re creating an array with 3 elements, i.e. max index up till 2. But when
we try to access the 4th index, it will raise an exception of index out of range and will be caught
in the except block. But here we need to observe that the finally block has also been triggered.
Unit 1 Chapter 5
Python Functions
Function refers to a named sequence of statements or a piece of code that performs a specific
task. We use functions whenever we need to perform the same task multiple times without
writing the same code again. It can take arguments and returns the value.
Python has a DRY principle like other programming languages. DRY stands for Don’t Repeat
Yourself. Consider a scenario where we need to do some action/tasks many times. We can
definethat action only once using a function and call that function whenever required to do
the same activity.
Function improves efficiency and reduces errors because of the reusability of a code. Once we
create a function, we can call it anywhere and anytime. The benefit of using a function is
reusability and modularity.
Types of Functions
Python support two types of functions
1. Built-in function
2. User-defined function
Built-in Functions
Built-in functions are already defined in python. A user has to remember the name and
parameters of a particular function. Since these functions are pre-defined, there is no need to
define them again.
Example:
l = [2, 5, 19, 7, 43]
print("Length of string is",len(l))
print("Maximum number in list is ",max(l))
print("Type is",type(l))
Output:
Length of string is 5
Maximum number in list is 43
Type is <class 'list'>
Function Description
sum() Sum() in Python returns the sum of all the items in an iterator
User-Defined Functions
These functions are defined by a programmer to perform any specific task or to reduce the
complexity of big problems and use that function according to their need.
Example:
def sub(x, y):
return x-y
print(sub(5,2))
Output:
3
Here,
• function_name: Function name is the name of the function. We can give any
name to function.
• parameter: Parameter is the value passed to the function. We can pass any number
of parameters. Function body uses the parameter’s value to perform an action
• function_body: The function body is a block of code that performs some task.
This block of code is nothing but the action you wanted to accomplish.
• return value: Return value is the output of the function.
Note: While defining a function, we use two keywords, def (mandatory) and return (optional).
Function calling
After creating a function in Python. we can call it by using the name of the function with the
parenthesis, and if the function accepts parameters, then pass those parameters in the
parenthesis.
def fun():
print("Welcome to PES")
fun()
Output:
Welcome to PES
Here,
• When the function is called, the control of the program goes to the function definition.
• All codes inside the function are executed.
• The control of the program jumps to the next statement after the function call.
Passing Parameters/Arguments
❖ Creating a function without any parameters
example of creating a simple function that prints a welcome message.
def message():
print("Welcome to PES")
# call function using its name
message()
Output
Welcome to PES
Let’s create a function that takes two parameters and displays their values.
In this example, we are creating function with two parameters ‘ name’ and ‘course_name’.
Output
Functions can return a value. The return value is the output of the function. Use the return
keyword to return value from a function.
Example:
def fun():
statement-1
statement-2
statement-3
.
.
return [expression]
Note: The return statement also denotes that the function has ended. Any code after return is
not executed.
Example
def find_square(num):
result = num * num
return result
square=find_square(3)
print('Square:',square)
# Output: Square: 9
In the above example, we have created a function named find_square(). The function
accepts a number and returns the square of the number.
You can also return multiple values from a function. Use the return statement by separating
each expression by a comma.
Example
In this example, we are returning three values from a function. We will also see how to
process or read multiple return values in our code.
1. Default arguments
2. keyword arguments
3. positional arguments
4. arbitrary positional arguments
5. arbitrary keyword arguments
Default Parameters:
• Default arguments are values that are provided while defining functions.
• The assignment operator = is used to assign a default value to the argument.
• Default arguments become optional during the function calls.
• If we provide a value to the default arguments during function calls, it overridesthe
default value.
• The function can have any number of default arguments
• Default arguments should follow non-default arguments.
Example:
In the below example, the default value is given to argument band c
def add(a,b=5,c=10):
return (a+b+c)
3 is assigned to a, 4 is assigned to b.
print(add(3,4))
#Output:17
3. Giving all the arguments
print(add(2,3,4))
#Output:9
Note: Default values are evaluated only once at the point of the function definition in the
defining scope. So, it makes a difference when we pass mutable objects like a list or dictionary
as default values.
Keyword Arguments:
Functions can also be called using keyword arguments of the form kwarg=value.
During a function call, values passed through arguments need not be in the order of parameters
in the function definition. This can be achieved by keyword arguments. But all the keyword
arguments should match the parameters in the function definition.
Example:
def add(a,b=5,c=10):
return (a+b+c)
Calling the function add by giving keyword arguments
1. All parameters are given as keyword arguments, so no need to maintain the same order.
print (add(b=10,c=15,a=20))
#Output:45
2. During a function call, only giving mandatory argument as a keyword argument. Optional
the operating system are known as Command Line Arguments it means allow you to pass
parameters to your python script when you run it from the command line. They provide a
way to make your scripts more flexible and configurable.
Using sys.argv
➢ The sys module provides access to command line arguments via the ‘sys.argv’ list.
‘sys.argv’ is a list of strings where the first term, ‘sys.argv[0]’, is the name of the
python script, and the subsequent items are the arguments provided when the script
is executed.
➢ We can access command line arguments by importing the ‘sys’ module and using
‘sys.argv’. for example, if we have a script called “myscript.py” and we run it with
‘python myscript.py arg1 arg2’, ‘sys.argv’ would be ‘[‘myscript.py’,’arg1’,’arg2’]’.
It’s main purpose are:
• It is a list of command line arguments.
• len(sys.argv) provides the number of command line arguments.
• sys.argv[0] is the name of the current Python script.
Example: Let’s suppose there is a Python script for adding two numbers and thenumbers
are passed as command-line arguments.
import sys
n = len(sys.argv)
print("Total arguments passed:", n)
print("\nName of Python script:", sys.argv[0])
print("\nArguments passed:", end = " ")
for i in range(1, n):
print(sys.argv[i], end = " ")
Sum = 0
for i in range(1, n):
Sum += int(sys.argv[i])
print("\n\nResult:", Sum)
Output:
Recursive Function
Recursive function in python is a function that calls itself in order to solve a problem. Such
functions that call themselves are known as recursive functions. A Recursive function
consists of two parts:
Example:
def factorial(n):
if n == 1:
return n
else:
return n * factorial(n-1)
# OUTPUT
print("Factorial of 5 using Recursion : ", factorial(5))
Output:
Consider, calculating the factorial of a number is a repetitive activity, in that case, we can call
a function again and again, which calculates factorial.
factorial(5)
5*factorial(4)
5*4*factorial(3)
5*4*3*factorial(2)
5*4*3*2*factorial(1)
5*4*3*2*1 = 120
1. The recursive function takes more memory and time for execution.
2. Debugging is not easy for the recursive function.
Scope and Lifetime of Variables in Functions
When we define a function with variables, then those variables’ scope is limited to that
function. In Python, the scope of a variable is an area where a variable is declared. It is called
the variable’s local scope.
We cannot access the local variables from outside of the function. Because the scope is local,
those variables are not visible from the outside of the function.
When we are executing a function, the life of the variables is up to running time. Once we
return from the function, those variables get destroyed. So function does no need to remember
the value of a variable from its previous call.
Example
global_lang = 'DataScience'
def var_scope_test():
local_lang = 'Python'
print(local_lang)
var_scope_test()
# Output 'Python'
# outside of function
print(global_lang)
# Output 'DataScience'
# NameError: name 'local_lang' is not defined
print(local_lang)
In the above example, we print the local and global variable values from outside of the
function. The global variable is accessible with its name global_lang.
But when we try to access the local variable with its name local_lang, we got a NameError,
because the local variable is not accessible from outside of the function.
A local variable is a variable declared inside the function that is not accessible from outside
of the function. The scope of the local variable is limited to that function only where it is
declared.
If we try to access the local variable from the outside of the function, we will get the error as
NameError.
Example
def function1():
loc_var = 888
print("Value is :", loc_var)
def function2():
print("Value is :", loc_var)
function1()
function2()
Output
Value is : 888
print("Value is :", loc_var) # gives error,
NameError: name 'loc_var' is not defined
A Global variable is a variable that declares outside of the function. The scope of a global
variable is broad. It is accessible in all functions of the same module.
Example
global_var = 999
def function1():
print("Value in 1nd function :", global_var)
def function2():
print("Value in 2nd function :", global_var)
function1()
function2()
Output
In Python, global is the keyword used to access the actual global variable from outside the
function. we use the global keyword for two purposes:
global_var = 5
def function1():
print("Value in 1st function :", global_var)
def function2():
global_var = 555
print("Value in 2nd function :", global_var)
def function3():
print("Value in 3rd function :", global_var)
function1(
function2()
function3()
Output
As you can see, function2() treated global_var as a new variable (local variable). To solve
such issues or access/modify global variables inside a function, we use the global keyword.
In Python, nonlocal is the keyword used to declare a variable that acts as a global variable for
a nested function (i.e., function within another function).
We can use a nonlocal keyword when we want to declare a variable in the local scope but act
as a global scope.
Example
def outer_func():
x = 777
def inner_func():
nonlocal x
x = 700
print("value of x inside inner function is :", x)
inner_func()
print("value of x inside outer function is :", x)
outer_func()
Output