PYTHON - 2
PYTHON - 2
ARGUMENT TO FUNCTIONS –
In programming, there are two ways in which arguments can be passed to functions: pass by value and
pass by reference. Some languages use pass by value by default while others use pass by reference.
Some languages support both and allow you to choose.
In Python, when an argument passed to a function is modified inside it, whether the change is visible
outside or not depends on whether the variable is mutable or not.
Programming languages allow controlling the ordering and default values of arguments.
TYPE OF VARABLES –
There are two types of variables which we can use in a program - local variables and global variables.
Local variables are the ones which are created inside a function. They are created when the owning
function starts execution and remains in memory till owning function finishes execution. They can be
accessed only inside that function.
Global variables are the ones which are created outside the functions. They are created when the
program execution starts and remains in memory till the program terminates. They can be read
anywhere in the program - within a function or outside.
VARIABLES AND ITS SCOPE –
wt_limit=30
def baggage_check(baggage_wt):
extra_baggage_charge=0
if not(baggage_wt>=0 and baggage_wt<=wt_limit):
extra_baggage=baggage_wt-wt_limit
extra_baggage_charge=extra_baggage*100
return extra_baggage_charge
def update_baggage_limit(new_wt_limit):
wt_limit=new_wt_limit
print("This airline now allows baggage limit till",wt_limit,"kgs")
print("This airline allows baggage limit till",wt_limit,"kgs")
print("Pay the extra baggage charge of",baggage_check(35),"rupees")
update_baggage_limit(45)
print("Pay the extra baggage charge of",baggage_check(35),"rupees")
OUTPUT-
In cases where a global variable needs to be modified inside a function, like in function
update_baggage_limit(), Python allows you to do that using the global keyword.
TESTING OF PROGRAMS –
UNIT TESTING -
Another way of ensuring that your code is correct is to test it following the below steps:
1. Identify values for input variables and its corresponding expected outputs based on business
requirements
3. Check whether the output is matching the expected output for the given input
4. If there is a match, it means that your code is working as expected for the given input
5. If not, it means that something has gone wrong in your code and you have to fix your code
If the code you are testing is written inside a function, invoke the function with different input values
and check whether the return value from the function is matching the expected output.
1. Path coverage
The information desk folks receive a lot of queries daily from passengers regarding the maximum weight
they can carry. They use a program which accepts the airline name and returns the maximum allowed
weight by that airline.
The maximum luggage weight allowed by the airlines that operate from this airport are as follows:
AI 30
EM 28
BA 35
Let’s see how we would test a program written for this scenario.
When we test a program, we need to first understand the logic that will be written for that program.
There are three decisions in this program namely D1, D2 and D3.
We have to identify airline values which will take the control through the true and false paths of each
decision, it is sufficient to cover the entire logic and uncover any error.
BOUNDARY VALUE ANALYSIS –
What if the programmer has written the condition like:
luggage_wt >= 1 and luggage_wt < 30?
Will it work as per the requirement for luggage weight of 30kg?
Whenever ranges (say >0 and <=30, >=30, >=1 and <=30 etc.) are being written in conditions, we need to
exhaustively test as most of the programmers make errors while writing these conditions. Hence it may
not be sufficient to check with just two values that take control to the true and false paths alone.
- on the boundary,
This technique of identifying test data on the boundaries is known as boundary value analysis.
The correct logic for the check-in process of Air India is as given below
The testing that we have been doing so far is known as unit testing.
Here, unit is the smallest testable part of a program or application, in our case a function. It is done to
check whether a unit is performing its intended task or not and it is the responsibility of the programmer
to test the piece of code that he/she has written.
Below are few of the unit testing techniques that can be used by the programmer to test the program.
Among these, we have learnt boundary value analysis and path/logic coverage.
EXCEPTION HANDLING –
Exception Handling using 'if' –
We got an error in the below code, one way to take care of such error situation is to use selection
constructs.
The error was due to addition of a string (“400”) to an integer. If we add a condition to check whether
the expenditure is of type int, that would solve this error. But that can cause further issues.
OUTPUT –
Wrong data type
600
list_of_values=[100,200,300,"400",500]
calculate_expenditure(list_of_values)
OUTPUT –
Some error occurred
Returning back from function.
## Python has many kinds of errors predefined as part of the language. Here are some of the common
types.
Built-in
When it will be raised Example
Exception
num_list=[]
ZeroDivisionError When a value is divided by zero total=10
avg=total/len(num_list)
When we try to do an operation with total=10
TypeError
incompatible data types total+="20"
When we try to access a variable
NameError avg=total/10 where total is not defined
which is not defined
When we try to access an index value num_list=[1,2,3,4]
IndexError
which is out of range value=num_list[4]
#string is a valid data type for int() but the
When we use a valid data type for an value “A” is invalid, as "A" can't be
ValueError argument of a built-in function but converted into int.
passes an invalid value for it value="A"
num=int(value)
Python also allows us to handle different errors that can occur separately. That means you can have a
different action or message for every unique error that occurs.
Here is the same expenditure calculation code with additional average expenditure calculation.
def calculate_expenditure(list_of_expenditure):
total=0
try:
for expenditure in list_of_expenditure:
total+=expenditure
print("Total:",total)
avg=total/num_values
print("Average:",avg)
except ZeroDivisionError:
print("Divide by Zero error")
except TypeError:
print("Wrong data type")
except:
print("Some error occurred")
list_of_values=[100,200,300,"400",500]
num_values=0
calculate_expenditure(list_of_values)
Note:
## If an error occurs inside a function and if the error is not caught inside it, then the error is transferred
to the function call where we have another opportunity to catch it.
def calculate_sum(list_of_expenditure):
total=0
try:
for expenditure in list_of_expenditure:
total+=expenditure
print("Total:",total)
avg=total/no_values
print("Average:",avg)
except ZeroDivisionError:
print("Divide by Zero error")
except TypeError:
print("Wrong data type")
try:
list_of_values=[100,200,300,400,500]
num_values=len(list_of_values)
calculate_sum(list_of_values)
except NameError:
print("Name error occured")
except:
print("Some error occured")
OUTPUT –
Total: 1500
Name error occurred
FINALLY BLOCK –
Sometimes in programming we need to execute some code irrespective of whether the primary
program logic itself succeeds or fails to do its job. In Python we can achieve this using a finally block.
A finally block of statement is an optional part of the try-except statements. A code written inside the
finally block will ALWAYS be executed.
balance=1000
amount="300Rs"
def take_card():
print("Take the card out of ATM")
try:
if balance>=int(amount):
print("Withdraw")
else:
print("Invalid amount")
except TypeError:
print("Type Error Occurred")
except ValueError:
print("Value Error Occurred")
except:
print("Some error Occurred")
finally:
take_card()
OUTPUT –
Value Error Occurred
Take the card out of ATM
RECURSIVE FUNCTIONS –
Human tower is created by men standing on shoulders of the men standing at the lower level. It can
have any number of levels. Each level will have 2 men less than the previous level. However, there will
always be one person at the top of the tower, that means there will always be odd number of men
standing at the bottom most/base level.
Suppose we want to find the total weight of a human tower which has 5 people standing at the bottom
level. Assume that each person weighs 50 kg and there will always be odd number of men at the base
level. We can solve this problem recursively.
In recursion, two things are important – termination condition and recursive call. Recursive call invokes
itself with a smaller argument and termination condition helps to terminate the recursive calls.
The termination condition of a recursive function if wrong, then it will end up calling itself infinitely
and the program may not stop or it may throw an error.
def human_tower(no_of_people):
if(no_of_people==0):
return 1*(50)
else:
return no_of_people*(50)+human_tower(no_of_people-2)
print("Total weight of human tower: ",human_tower(5))
OUTPUT-
Runtime Exception
Traceback (most recent call last):
File "file.py", line 6, in <module>
print("Total weight of human tower: ",human_tower(5))
File "file.py", line 5, in human_tower
return no_of_people*(50)+human_tower(no_of_people-2)
File "file.py", line 5, in human_tower
return no_of_people*(50)+human_tower(no_of_people-2)
File "file.py", line 5, in human_tower
return no_of_people*(50)+human_tower(no_of_people-2)
[Previous line repeated 995 more times]
File "file.py", line 2, in human_tower
if(no_of_people==0):
RecursionError: maximum recursion depth exceeded in comparison
Tower of Hanoi is another problem which can be used to learn recursion. This problem was discovered
by the French mathematician Edouard Lucas in 1883.
Rules :
Move only one disk at a time. Rings must be in decreasing size
No move should result in a larger disk on top of a smaller disk
For temporarily holding a disk, the third tower can be used
Let’s understand how the solution can be defined recursively for transferring 3 rings from tower A to
tower B.
Step-1: Two rings moved from tower A to tower C
solution is arrived for 2 rings using A as source tower, C as destination tower and B as temp
tower
Step-2: A ring is transferred from tower A to tower B
Step-3: Two rings moved from tower C to tower B
solution is arrived for 2 rings using C as source tower, B as destination tower and A as temp
tower
source=["blue","green","orange"]
destination=[]
temp=[]
tower_of_hanoi(3, source, destination, temp)
print("Source:",source)
print("Destination:",destination)
Output:
Source: []
Destination: ['blue', 'green', 'orange']
Let's assume that the ManageFlights.py inside Flights package has the below code:
airline="Smart Airlines"
def add(no_of_flights):
print(no_of_flights," flights added to the fleet")
If we need to access the function add(), inside the ManageFlights module in some other module, then
we can import the ManageFlights module and use it.
Import can be done in two ways:
Method 1:
Method 2:
## Consider a scenario where 2 modules have the same name but in different package and both of them
have the same function ‘add’.
Flights->Manage.py->add()
Employees->Manage.py->add()
To avoid naming conflicts during import we can use one of the below techniques:
1. import Flights.Manage
import Employees.Manage
Flights.Manage.add()
Employees.Manage.add()
FManage.add()
EManage.add()
add1()
add2()
FILE HANDLING IN PYTHON –
Python allows to create files, read from files, write content to file and append content to existing
content through inbuilt functions!
Method Description
This method is used to open the file for the specified operation. The
open(file_path,operation)
operation can either be r,w,a for read, write and append.
close() This method is used to close a file which is already open.
This method is used to write a string to a file, if file is present. If not, it creates
write()
the file and writes the string into it.
read() This method is used to read all the contents of a file into a string.
The number of files that can be simultaneously opened by a program is limited. So it is very important to
close all the files, once the operations are completed.
flight_file=open("flight.txt","w")
flight_file.write("Hello")
flight_file.close()
try:
flight_file=open("flight.txt","r")
text=flight_file.read()
print(text)
flight_file.write(",Good Morning")
flight_file.close()
except:
print("Error occurred")
if flight_file.closed:
print("File is closed")
else:
print("File is open")
Though we are catching the exception in this example, we observe that the file will not be closed, as the
close statement is after the exception raising line.
try:
flight_file=open("flight.txt","r")
text=flight_file.read()
print(text)
flight_file.write(",Good Morning") #Exception occurs in this line
flight_file.close()#This line will not be executed
except:
print("Error occurred")
if flight_file.closed:
print("File is closed")
else:
print("File is open")
When we want to write a code that will run in all situations, we can put it in a finally block.
Since closing a file is necessary we can do it in the finally block instead of in the try block.
try:
flight_file=open("flight.txt","r")
text=flight_file.read()
print(text)
flight_file.write(",Good Morning")
except:
print("Error occurred")
finally:
print("File is being closed")
flight_file.close()
if flight_file.closed:
print("File is closed")
else:
print("File is open")
COMMON MISTAKES –
My code returns the correct value on execution but test cases fail when I verify.
Possible Cause:
You might be using global variables (from driver code) instead of parameters inside your function. Your
function alone is considered for verification. Any driver code outside your function is discarded for
verification.
Example:
Given a word and an integer position as parameters, the function below returns the character at
position if the word is long enough otherwise it returns 'X'.
My code is returning the correct data but my logical test cases fail.
Possible Cause:
You may be returning the correct value but wrong data type from your method. For instance, returning
a string instead of integer.
Example:
The method below is expected to concatenate contents of two input lists and return the result as a
string.
This function returns a list [a, b, c, d] instead of the string "abcd". The data is correct but its data type is
incorrect.
How do I fix it?
Always use correct data type while returning from a function. Sample test cases will give you a good idea
of data type that is expected.
------------------------------------------------------------------------------------------------------------------------------------------
No matter what I do my code always returns "None" for some or all of my inputs.
Possible Cause:
You might have wrongly indented the return statement. By default a function implicitly returns "None".
Example:
The method below returns the rate of interest based on the amount:
def calc_rate(amount):
if(amount > 0 and amount <= 45000):
rate = 7.0
elif(amount > 46000):
rate = 9.5
return rate
print(calc_rate(10000))
Here, the statement "return rate" is indented wrongly and is part of "elif" block. Since the amount is less
than 45000, the first if is evaluated to true and the statement "rate = 7.0" is executed. The control then
reaches the end of function where there is no return statement. So the function implicitly returns
"None" and the calculated rate is lost.
How do I fix it?
Carefully indent your code and ensure that your return statements are in the right block of code.
------------------------------------------------------------------------------------------------------------------------------------------
My code is giving the correct output on execution but test cases fail on verification
Possible Cause:
You may not be removing unnecessary leading and trailing spaces in the output. A string comparison
between your output string and the expected string would fail if your string has unnecessary spaces.
Example:
The method format_name is required to take a string that has first name and last name separated using
a colon and return the full name with a space between the first and last name
def format_name(name):
splitdata = name.split(':')
result = ""
for namepart in splitdata:
result += namepart
return result
print(format_name(" Joe : Smith "))
Here, the output is " Joe Smith " instead of "Joe Smith". The leading and trailing spaces cause the test
cases to fail even though the names are correct.
How do I fix it?
1. Ensure that you trim the leading and trailing spaces as per your requirement.
2. Be careful while entering string values and ensure there are no additional spaces. For instance,
the right way to fix the code in the above example is:
def split_data(name):
splitdata = name.split(':')
result = ""
for namepart in splitdata:
result += ' ' + namepart.replace(' ','')
return result
print(split_data(" Joe : Smith "))
Here, you remove the spaces from the individual parts of the name using replace method.
------------------------------------------------------------------------------------------------------------------------------------------
My code uses a dictionary. When I verify sometimes the test cases pass and sometimes they fail for the
same code. How is it possible?
Possible Cause:
You may be fetching the value for a key improperly
Example:
The method fetch_fee is required to take a course as input and return the fee for that course, if the
course is invalid then it returns -1
dict1 = {"BTech":50000,"MTech":60000,"MCA":30000,"BCA":25000}
def fetch_fee(course):
for key,value in dict1.items():
if(key == course):
return value
else:
return -1
print(fetch_fee("MTech"))
Here, when you execute the code multiple times you will observe that the output varies for few of the
executions (-1 or 60000).This is because across executions the order of elements in dictionary is not the
same.
How do I fix it?
The right way to fetch values from the dictionary is:
dict1 = {"BTech":50000,"MTech":60000,"MCA":30000,"BCA":25000}
def fetch_fee(course):
if(course in dict1.keys())
return dict1[course]
else:
return -1
print(fetch_fee("MTech"))
Here, you do not loop through the elements but use the 'in' clause for checking existence of key and
then retrieve the value from the dictionary using the key as the index.
------------------------------------------------------------------------------------------------------------------------------------------
My logic while working with strings is correct but some test cases are failing
Possible Cause:
You may be missing some boundary conditions
Example:
The method is_substr takes as input strings str1 and word determines if str1 is a substring of word.
Thus the nested loops to create all possible substrings possible for a given word is completely avoided
making the code simple.
------------------------------------------------------------------------------------------------------------------------------------------
I am trying to delete elements from a list but its not deleting properly.
Possible Cause:
You may be messing up the indices.
Example:
The function, delete_ones takes as input num_list, deletes all occurrences of 1 from the num_list and
returns it.
def delete_ones(num_list):
for index, num in enumerate(num_list):
if(num == 1):
num_list.pop(index)
return num_list
num_list = [1,1,2,1]
print(delete_ones(num_list)
def delete_ones(num_list):
temp_list = []
#Copy the elements other than 1 to temp_list
for num in num_list:
if(num != 1):
temp_list.append(num)
#Copy temp_list to num_list
num_list = temp_list
return num_list
num_list = [1,1,2,1]
print(delete_ones(num_list))