UNIT 2_Python
UNIT 2_Python
Lists in Python
A built - in data type that stores set of values.
It can store elements of different types (integer, float, string, etc.)
marks = [87, 64, 33, 95, 76] # marks[0], marks[1] …
student = [“karan”, 85, “Delhi”] #student[0], student[1]…
student[0] = “Arjun” #allowed in python
len(student) #returns length
Note: Strings are immutable and lists are mutable in python. Mutable
means to change and immutable means not changed.
Example:
str = "hello"
print(str[0])
str[0] = "y"
List Slicing
Similar to String Slicing.
List_name[starting_idx: ending_idx] #ending index is not included
marks = [87, 64, 33, 95, 76]
marks[1:4] is [64,33,95]
marks[ :4] is same as marks[0:4]
marks[1: ] is same as marks[1:len(marks)]
marks[-3:-1] is [33,95]
List Methods
list = [2, 1, 3]
list.append(4) #adds one element at the end [2, 1, 3, 4]
list.sort() #sorts in ascending order [1, 2, 3]
list.sort(reverse = True) #sorts in descending order [3, 2, 1]
list.reverse() #reverses list [3, 1, 2]
list.insert(idx, el) #insert element at index
If list = [2, 1, 3, 1]
list.remove(1) #removes first occurrence of element [2, 3, 1]
list.pop(idx) #removes element at idx
Note: we have lots of methods with list in visual studio. For example, if
we type list. In visual studio then it will show so many methods as
shown below:
Output:
After append: [10, 20, 30, 40]
After extend: [10, 20, 30, 40, 50, 60]
After insert: [10, 15, 20, 30, 40, 50, 60]
After remove: [10, 15, 20, 40, 50, 60]
After pop: [10, 15, 20, 40, 50] Popped element: 60
After clear: []
Index of 40: 3
Count of 20: 1
After sort (descending): [50, 40, 30, 20, 10]
After reverse: [10, 20, 30, 40, 50]
Copied list: [10, 20, 30, 40, 50]
Tuples in Python
A built-in data type that lets us create immutable sequences of values.
tup = (87, 64, 33, 95, 76) #tup[0], tup[1]…
tup[0] = 43 #not allowed in python
Note: We can access value but cannot assign value in tuple.
tup1 = ( )
tup2 = ( 1, )
tup3 = (1, 2, 3)
tup = ( )
print(tup)
print(type(tup))
tup =("hello")
print(tup)
print(type(tup))
Tuple Methods
tup(2, 1, 3, 1)
tup.index(el) #returns index of first occurrence tup.index(1) is 1
tup.count(el) #counts total occurrences tup.count(1) is 2
tup =(1, 2, 3, 4) tup =(1, 2, 3, 4, 2, 2)
print(tup.index(2)) print(tup.count(2))
print(movies)
Dictionary in Python
Dictionaries are used to store data values in key: value pairs.
They are unordered, mutable(changeable) & don’t allow duplicate keys.
(string, list and tuple have index so they are ordered.)
Output:
null_dict = { }
print(null_dict)
Nested Dictionaries
Dictionary under dictionary
student = {
"name" : "Kauleshwar Prasad",
"subjects" : {
"phy" : 97,
"chem" : 98,
"math" : 95
#nested dictionary(subject dictionary under student dictionary)
}
}
print(student) # to display values of student dictionary
print(student["subjects"]) # to display values of subjects dictionary
print(student["subjects"]["chem"]) #to display marks of chem
Dictionary Methods
myDict.keys( ) #returns all keys
myDict.values( ) #returns all values
myDict.items( ) #returns all (key, val) pairs as tuples
myDict.get( “key““ ) # returns the value associated with the specified key in
the dictionary. If the key is not found, .get() returns None
myDict.update( newDict ) #inserts the specified items to the dictionary
student = {
"name" : "Kauleshwar Prasad",
"subjects" : {
"phy" : 97,
"chem" : 98,
"math" : 95
#nested dictionary(subject dictionary under student dictionary)
}
}
print(student.keys()) #returns all keys.
student = {
"name" : "Kauleshwar Prasad",
"subjects" : {
"phy" : 97,
"chem" : 98,
"math" : 95
#nested dictionary(subject dictionary under student dictionary)
}
}
print(student.values()) #returns all values
student = {
"name" : "Kauleshwar Prasad",
"subjects" : {
"phy" : 97,
"chem" : 98,
"math" : 95
student = {
"name" : "Kauleshwar Prasad",
"subjects" : {
"phy" : 97,
"chem" : 98,
"math" : 95
#nested dictionary(subject dictionary under student dictionary)
}
}
print(student.get("name")) #return key according to the value
student = {
"name" : "Kauleshwar Prasad",
"subjects" : {
"phy" : 97,
"chem" : 98,
"math" : 95
}
}
student.update({"city": "delhi"}) #new key value pair updated
print(student)
Set in Python
Set is the collection of the unordered items.
Each element in the set must be unique & immutable.
List and dictionary cannot be stored in set because both are mutable.
Int, float, string, tuple and Boolean can be stored in set.
nums = { 1, 2, 3, 4 }
set2 = { 1, 2, 2, 2 } #repeated elements stored only once, so it resolved to {1,
2}
null_set = set( ) #empty set syntax
Set Methods
set.add( el ) #adds an element
set.remove( el ) #removes the element
set.clear( ) #empties the set
set.pop( ) #removes a random value
set.union( set2 ) #combines both set values & returns new
set.intersection( set2 ) #combines common values & returns new
dictionary = {
"cat" :"a small animal",
"table": ["a piece of furniture", "list of facts and figures"]
}
print(dictionary)
You are given a list of subjects for students. Assume one classroom is
required for 1 subject. How many classrooms are needed by all
students. ”python”, “java”, “C++”, “python”, “javascript”, “java”,
“python”, “java”, “C++”, “C
subjects = {
"python", "java", "c++", "python","javascript”, “java”, “python”, “java”,
“C++”, “C"
}
print(len(subjects))
WAP to enter marks of 3 subjects from the user and store them in a
dictionary. Start with an empty dictionary & add one by one. Use
subject name as key & marks as value.
marks = { }
print(marks)
Figure out a way to store 9 & 9.0 as separate values in the set. (You
can take help of built-in data types)
values = {
("float", 9.0),
("int", 9)
}
print(values)
Functions in Python
• If a group of statements is repeatedly required then it is not recommended
to write these statements every time separately. We must define these
statements as a single unit and we can call that unit any number of times
based on our requirement without rewriting. This unit is nothing but
function.
• The main advantage of functions is code Reusability.
• In other languages, functions are known as methods, procedures,
subroutines etc.
a = 20
b = 10
print('The Sum : ', a + b)
print('The Difference : ', a - b)
print('The Product : ', a * b)
Output:
The Sum : 30
The Difference : 10
The Product : 200
a = 20
b = 10
print('The Sum : ', a + b)
print('The Difference : ', a - b)
print('The Product : ', a * b)
a = 200
b = 100
print('The Sum : ', a + b)
print('The Difference : ', a - b)
print('The Product : ', a * b)
Output:
The Sum : 30
The Difference : 10
The Product : 200
Output:
The Sum : 30
The Difference : 10
The Product : 200
The Sum : 300
The Difference : 100
The Product : 20000
The Sum : 3000
The Difference : 1000
The Product : 2000000
Here the same code (3 lines) is repeating thrice in the code. Generally we never
recommended to wrtie the group of statements repeatedly in the program.
Problems of writing the same code repeatedly in the program:
1. Length of the program increases.
2. Readability of the program decreases.
3. No Code Reusabilty.
Solution of the above problem:
def calculate(a,b):
print('The Sum : ', a + b)
print('The Difference : ', a - b)
print('The Product : ', a * b)
a = 20
b = 10
calculate(a,b)
Output:
The Sum : 30
The Difference : 10
The Product : 200
The Sum : 300
The Difference : 100
The Product : 20000
def calculate(a,b):
print('The Sum : ', a + b)
print('The Difference : ', a - b)
print('The Product : ', a * b)
a = 20
b = 10
calculate(a,b)
a = 200
b = 100
calculate(a,b)
a = 2000
b = 1000
calculate(a,b)
Output:
The Sum : 30
The Difference : 10
The Product : 200
The Sum : 300
The Difference : 100
The Product : 20000
The Sum : 3000
The Difference : 1000
The Product : 2000000
Output:
The Sum : 30
The Difference : 10
The Product : 200
The Sum : 300
The Difference : 100
The Product : 20000
The Sum : 3000
The Difference : 1000
The Product : 2000000
Note: We are writing the function once and calling that function 'n'
times.
Practice Questions
1. WAP which defines a function called add_numbers to add two
numbers and returns the result. Both numbers will be given as input
from user.
# Main program
num1 = float(input("Enter the first number: "))
num2 = float(input("Enter the second number: "))
def wish():
print("Hello Good Morning")
wish()
wish()
wish()
Output:
Hello Good Morning
Hello Good Morning
Hello Good Morning
Output:
(150, 50, 5000, 2.0)
def calc(a,b): # Positional Arguments
sum = a + b
sub = a - b
mul = a * b
div = a / b
return sum,sub,mul,div # In Python, when you return multiple values separated
by commas, they are returned as a tuple.
t = calc(100,50)
for x in t:
print(x)
Note: A for loop is used to iterate over the tuple t. During each iteration, the
variable x takes the value of the current element in the tuple.
Output:
150
50
5000
2.0
If we want to write above program without return statement then
program is as follows:
# Function call
calc(100, 50)
Use of return
In this example, the calc function returns the sum of a and b, which
can be stored in a variable and printed later. This separation allows you
to use result for additional computations or decisions later in your
program.
While printing values directly can be simpler for small, one-off scripts
or quick tests, using return is a better practice for creating reusable,
maintainable, and flexible code, especially in larger programs or when
building libraries.
Output:
150
50
5000
2.0
def calc(a,b): # keyword Arguments
sum = a + b
sub = a - b
mul = a * b
div = a / b
return sum,sub,mul,div
t = calc(100,b = 50) #perfectly valid
for x in t:
print(x)
Output:
150
50
5000
2.0
def calc(a,b): # keyword Arguments
sum = a + b
sub = a - b
mul = a * b
div = a / b
return sum,sub,mul,div
t = calc(b = 50, 100) # It is invalid, because positional argument
should follow keyword argument
for x in t:
print(x)
def check_even_odd(num):
if num % 2 == 0:
return "Even"
else:
return "Odd"
# Main program
number = int(input("Enter a number: "))
result = check_even_odd(number)
print(f"The number {number} is {result}.")
def factorial(n):
if n == 0 or n == 1:
return 1
else:
return n * factorial(n - 1)
# Main program
num = int(input("Enter a number: "))
fact = factorial(num)
print(f"The factorial of {num} is {fact}.")
# Main program
def reverse_string(s):
return s[::-1]
# Main program
string = input("Enter a string: ")
reversed_str = reverse_string(string)
print(f"The reversed string is: {reversed_str}")
def is_palindrome(s):
return s == s[::-1]
# Main program
string = input("Enter a string: ")
if is_palindrome(string):
print(f"'{string}' is a palindrome.")
else:
print(f"'{string}' is not a palindrome.")
3. Default Parameters:
def greet(name="BITIANS"):
print(f"Hello, {name}!")
• In the example, name=" BITIANS " means that name has a default value
of " BITIANS ".
Output:
Hello Guest Good Morning
def wish(marks,age,name = 'Guest', msg = 'Good Morning'):
print('Student Name:',name)
print('Student Age:',age)
print('Student Marks:',marks)
print('Message:',msg)
wish(99,48,'Karthi') # Valid
Output:
Student Name: Karthi
Student Age: 48
Student Marks: 99
Message: Good Morning
Output:
Student Name: Guest
Student Age: 48
Student Marks: 100
Message: Good Morning
Output:
Student Name: Karthi
Student Age: 46
Student Marks: 100
Message: Bad Morning
def sum(a,b):
print(a+b)
sum(10,20)
Output:
30
def sum(a,b):
print(a+b)
sum(10,20,30)
It will give error as follows:
TypeError: sum() takes 2 positional arguments but 3 were given
def sum(a,b,c):
print(a+b+c)
sum(10,20,30) # we have to go for another sum() function
Output:
60
Now it is working correctly.
def sum(a,b,c):
print(a+b+c)
sum(10,20,30,40)
Output:
TypeError: sum() takes 3 positional arguments but 4 were given
def sum(a,b,c,d):
print(a+b+c+d)
sum(10,20,30,40) # we have to go for another sum() function
Output:
100
def sum(*n):
result =0
for x in n:
result = result + x
print(result)
sum(10,20,30,40) # Here, 'n' is a variable length argument.
Description:
3. for x in n:
• The function loops over each element in the tuple n (which contains
all the arguments passed to the function).
Output:
The Sum is : 100
The Sum is : 60
The Sum is : 30
The Sum is : 10
The Sum is : 0
def sum(*n,name):
result =0
for x in n:
result = result + x
print("The Sum by", name, ": ", result)
sum(10,20,30,40,name = 'Robin')
sum(10,20,30,name = 'Rahul')
sum(10,20,name = 'Sachin')
sum(10,name = 'Sourav')
sum(name ='Karthi')
Output:
The Sum by Robin : 100
The Sum by Rahul : 60
The Sum by Sachin : 30
The Sum by Sourav : 10
The Sum by Karthi : 0
def f(arg1,arg2,arg3=4,arg4=8):
print(arg1,arg2,arg3,arg4)
f(3,2) #3 2 4 8
f(10,20,30,40) # 10,20,30,40
f(25,50,arg4=100) # 25 50 4 100
f(arg4=2,arg1=3,arg2=4) #3442
#f()
TypeError: f() missing 2 required positional arguments: 'arg1' and 'arg2'
#f(arg3=10,arg4=20,30,40)
SyntaxError: positional argument follows keyword argument
#f(4,5,arg2=6)
TypeError: f() got multiple values for argument 'arg2'
#f(4,5,arg3=5,arg5=6)
TypeError: f() got an unexpected keyword argument 'arg5'
Output:
3248
10 20 30 40
25 50 4 100
3442
Types of Variables:
Python supports 2 types of variables.
1. Global Variables
2. Local Variables
1. Global Variables:
• The variables which are declared outside of function are called global
variables.
• These variables can be accessed in all functions of that module.
Consider the following example
a = 10 # Global Variables
def f1():
a = 20 # Local variable to the function 'f1'
print(a) # 20
def f2():
print(a) # 10
f1()
f2()
Output:
20
10
Suppose our requirement is, we don't want local variable. For that, one special
keyword is used, called as global.
global keyword: We can use global keyword for the following 2 purposes:
1. To declare global variables explicitly inside function.
Output:
777
10
a = 10 # Global Variables
def f1():
a = 20 # Local variable to the function 'f1'
print(a) # 20
def f2():
print(a) # 10
f1()
f2()
Output:
777
777
Description:
global a declares that a inside f1 refers to the global variable a.
a = 777 assigns the value 777 to the global variable a.
def f1():
x = 10 # local variable of 'f1()'
print(x)
def f2():
Output:
10
NameError: name 'x' is not defined
def f1():
global x
x=10
print(x)
Output:
10
10
def f1():
global a
a = 888
print('f1 :',a)
def f2():
global a
a=999
print('f2 :',a)
f1()
f2()
Output:
f1 : 888
f2 : 999
def f1():
global a
a = 888
print('f1 :',a)
def f2():
global a
a=999
print('f2 :',a)
def f3():
print('f3 :',a)
f1()
f2()
f3()
Output:
f1 : 888
f2 : 999
f3 : 999
def f1():
global a
a = 888
print('f1 :',a)
def f2():
global a
Output:
f2 : 999
f1 : 888
If global variable and local variable having the same name, then we can
access global variable inside a function using globals() function.
Output:
777
10
Example 1:
Output:
Explanation:
1. *args collects all the positional arguments (e.g., 1, 2, 3) into a tuple.
2. **kwargs collects all the keyword arguments (e.g., name="John",
age=30) into a dictionary.
We can use *args and **kwargs when we are not sure how many arguments
will be passed to the function.
Example 2:
Output:
Positional Arguments:
Apple
Banana
Orange
Keyword Arguments:
name: John
age: 25
city: New York
Recursive Functions
A function that calls itself is known as Recursive Function.
The main advantages of recursive functions are:
1. We can reduce length of the code and improves readability.
2. We can solve complex problems very easily. For example, Towers of Hanoi,
Ackerman's Problem etc.
def factorial(n):
if n==0:
result=1
else:
result=n*factorial(n-1)
return result
print("Factorial of 0 is :",factorial(0))
print("Factorial of 4 is :",factorial(4))
print("Factorial of 5 is :",factorial(5))
print("Factorial of 40 is :",factorial(40))
Output:
Factorial of 0 is : 1
Factorial of 4 is : 24
Factorial of 5 is : 120
Factorial of 40 is
815915283247897734345611269596115894272000000000
Anonymous Functions
# A regular function
def add(x, y):
return x + y
numbers = [1, 2, 3, 4]
squared = list(map(lambda x: x ** 2, numbers))
print(squared) # Output: [1, 4, 9, 16]
numbers = [11,20,31,40,51,60,71,80,91,100]
city = ['jaipur','kota','chandigarh','delhi','muzaffarpur']
def length(city):
return len(city)
sort = sorted(city, key=length)
print("sorted words by length:", sort)
Output:
['kota', 'delhi', 'jaipur', 'chandigarh', 'muzaffarpur']
Output:
sorted words by length: ['kota', 'delhi', 'jaipur', 'chandigarh',
'muzaffarpur']
If we want to print in reverse order then
city = ['jaipur','kota','chandigarh','delhi','muzaffarpur']
Output:
sorted words by length: ['muzaffarpur', 'chandigarh', 'jaipur',
'delhi', 'kota']
OOPS in Python
To map with real world scenarios, we started using objects in code. This is
called object-oriented programming. Object-Oriented Programming (OOP) is
a programming paradigm that involves designing programs around concepts
represented as "objects". Python supports OOP through the provision of
classes.
s2 = Student()
print(s2.name)
Kauleshwar Prasad
Kauleshwar Prasad
#creating class
class Car: #class name starts with capital letter
colour = "blue"
brand = "mercedes"
#creating object (instances)
s1 = Car()
print(s1.colour)
print(s1.brand)
output:
blue
mercedes
class Person:
def __init__(self, name, age):
self.name = name
self.age = age
p1 = Person("Kauleshwar", 42)
print(p1)
Output:
Kauleshwar(42)
Object Methods
Objects can also contain methods. Methods in objects are
functions that belong to the object.
def myfunc(self):
print("Hello my name is " + self.name)
print(f"My age is {self.age}" )
p1 = Person("Kauleshwar", 42)
p1.myfunc()
Output:
class Person:
def __init__(mysillyobject, name, age):
mysillyobject.name = name
mysillyobject.age = age
def myfunc(abc):
p1 = Person("Kauleshwar", 42)
p1.myfunc()
Output:
def myfunc(self):
print("Hello my name is " + self.name)
p1 = Person("Kauleshwar", 42)
p1.age = 40
print(p1.age)
Output:
40
Apart from __init__() and __str__(), there are several other special (or "magic")
methods in Python, commonly used to customize behavior in classes. Here
are a few:
1. __repr__(): Provides an unambiguous string representation, often used
for debugging.
2. __len__(): Returns the length of an object (used in len()).
3. __getitem__(): Allows indexing like lists or dictionaries.
Python Inheritance
• Inheritance allows us to define a class that inherits all the methods and
properties from another class.
• Parent class is the class being inherited from, also called base class.
• Child class is the class that inherits from another class, also called derived
class.
# Child class
class Dog(Animal):
def speak(self):
print(f"{self.name} barks.")
# Creating objects
a = Animal("Animal")
d = Dog("Dog")
An example of Python inheritance with two child ( Dog & Cat )of class
Animal:
# Parent class
class Animal:
def __init__(self, name):
def speak(self):
print(f"{self.name} makes a sound.")
# Child class 1
class Dog(Animal):
def speak(self):
print(f"{self.name} barks.")
# Child class 2
class Cat(Animal):
def speak(self):
print(f"{self.name} meows.")
# Creating objects
dog = Dog("Buddy")
cat = Cat("Whiskers")
class Dog(Animal):
def __init__(self, name, breed):
super().__init__(name) # Calls the parent's constructor
self.breed = breed
class Animal:
def sound(self):
print("Animal makes sound")
class Dog(Animal):
def bark(self):
print("Dog barks")
class Puppy(Dog):
def cute(self):
print("Puppy is cute")
p = Puppy()
p.sound() # Inherited from Animal
p.bark() # Inherited from Dog
p.cute() # Puppy method
Output:
Animal makes sound
Dog barks
Puppy is cute
Multiple inheritance
Multiple inheritance in Python allows a class to inherit attributes
and methods from more than one parent class. This enables a
class to acquire functionality from multiple sources.
Output:
Father: Tall
If you want to call both the Father and Mother methods, you can
explicitly call them using their class names in the child class
method, like this:
class Father:
def traits(self):
print("Father: Tall")
class Mother:
def traits(self):
print("Mother: Intelligent")
c = Child()
c.traits() # Calls both Father and Mother's traits methods
Output:
Father: Tall
Mother: Intelligent
c = Child()
c.traits() # Calls both Father
and Mother's traits methods
class B(A):
def display(self):
print("Display method from class B")
class C(A):
def display(self):
print("Display method from class C")
d = D()
d.display()
Output:
[<class '__main__.D'>, <class '__main__.B'>, <class '__main__.C'>, <class
'__main__.A'>, <class 'object'>]
This means, when calling a method, Python will first look in class D, then B,
then C, then A, and finally, if nothing is found, in the built-in object class.
Solution using super():
To solve this, you can use super() inside the display method of the classes B
and C. The super() function ensures that Python follows the MRO and calls
methods in the correct order, avoiding ambiguity.
class A:
def display(self):
print("Display method from class A")
class B(A):
def display(self):
super().display() # Call the method from the next class in MRO
print("Display method from class B")
class C(A):
def display(self):
super().display() # Call the method from the next class in MRO
print("Display method from class C")
d = D()
d.display()
Output:
Hierarchical inheritance
Hierarchical inheritance is a type of inheritance in object-oriented
programming where multiple derived classes inherit from a single base class.
In other words, it involves one parent class and many child classes that extend
the functionality of the parent.
# Base class
class Animal:
def speak(self):
print("This animal makes a sound")
# Derived class 1
class Dog(Animal):
def speak(self):
print("The dog barks")
# Derived class 2
class Cat(Animal):
def speak(self):
print("The cat meows")
# Derived class 3
class Cow(Animal):
def speak(self):
print("The cow moos")
Description
In this example, the base class Animal is inherited by three derived classes:
Dog, Cat, and Cow. Each derived class overrides the speak() method,
demonstrating how hierarchical inheritance allows multiple child classes to
share the same parent while customizing or extending its functionality.
Encapsulation in Python
• Encapsulation is one of the fundamental concepts in object-oriented
programming (OOP).
• It describes the idea of wrapping data and the methods that work on data
within one unit.
• This puts restrictions on accessing variables and methods directly and can
prevent the accidental modification of data.
• To prevent accidental change, an object’s variable can only be changed by
an object’s method.
• Those types of variables are known as private variables.
• The goal of information hiding is to ensure that an object’s state is always
valid by controlling access to attributes that are hidden from the outside
world.
• This is also used to protect the object's internal state and ensure controlled
access via public methods (getters and setters).
• Encapsulation is achieved by defining variables as private or protected and
providing methods to access and modify them.
Output:
John
50000
55000
Invalid salary amount!
Description
Polymorphism in Python
• The literal meaning of polymorphism is the condition of occurrence in
different forms.
• Polymorphism is a very important concept in programming. It refers to the
use of a single type entity (method, operator or object) to represent different
types in different scenarios.
Let's take an example:
We know that the + operator is used extensively in Python programs. But, it
does not have a single usage.
For integer data types, + operator is used to perform arithmetic addition
operation.
num1 = 1
num2 = 2
print(num1+num2)
output
3
Output
Python Programming
Output
9
3
2