0% found this document useful (0 votes)
6 views47 pages

Unit-1 Basics of Object Oriented Programming

The document outlines the curriculum for a course on AI-Oriented Programming and Data Structures in Python, focusing on Object-Oriented Programming (OOP) concepts such as classes, objects, encapsulation, inheritance, and polymorphism. It includes detailed explanations of key OOP principles, constructors, destructors, and various types of inheritance. Additionally, it provides examples and use cases to illustrate the application of these concepts in Python programming.

Uploaded by

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

Unit-1 Basics of Object Oriented Programming

The document outlines the curriculum for a course on AI-Oriented Programming and Data Structures in Python, focusing on Object-Oriented Programming (OOP) concepts such as classes, objects, encapsulation, inheritance, and polymorphism. It includes detailed explanations of key OOP principles, constructors, destructors, and various types of inheritance. Additionally, it provides examples and use cases to illustrate the application of these concepts in Python programming.

Uploaded by

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

Set 304-05 AI-Oriented Programming and Data Structures in Python

(A.I.O.P.D.)

Unit-1: Basics of Object Oriented Programming:


1.1 Concepts of Class and Object in Python
(Defining classes, objects, and the self-keyword)
1.2 Data Encapsulation and Inheritance:
1.2.1 Access control concepts (Public, Private, Protected) and their difference in
Python
1.2.2 Declaring simple class, member variables, and member functions in Python
1.2.3 Concepts of Data hiding, abstraction, and encapsulation in Python.
1.2.4 Concepts of Inheritance in Python and types of inheritance (Single, Multiple, Multilevel)
1.2.5 Constructors (__init__) and Destructors (__del__) in Python
1.3 Polymorphism:
1.3.1 Concepts of Polymorphism in Python
1.3.2 Compile-time and run-time Polymorphism in Python
1.3.3 Method Overloading and Overriding in Python:
Concepts, difference, and application
1.4 Introduction to Data Structures and their application areas in Python (using lists, sets, tuples,
dictionaries)
1.4.1 Difference between Linear and Non-Linear Data Structures in Python

Object-Oriented Programming (OOP):


Object-Oriented Programming (OOP) is a programming that uses objects and classes to organize
code. It helps in writing reusable, scalable, and organized programs.

Object Oriented Programming is a fundamental concept in Python, empowering developers to


build modular, maintainable, and scalable applications. By understanding the core OOP
principles (classes, objects, inheritance, encapsulation, polymorphism, and abstraction etc).

OOPs Concepts in Python


 Class in Python
 Objects in Python
 Encapsulation in Python
 Inheritance in Python
 Polymorphism in Python
 Data Abstraction in Python

Class
 A class is a collection of objects.
 A class is a blueprint for creating objects.
 It defines attributes (variables) and methods (functions).

The __init__() Function (Constructors)


 To understand the meaning of classes we have to understand the built
in __init__() function.
 All classes have a function called __init__(), which is always executed when the class is
being initiated.
 Use the __init__() function to assign values to object properties, or other operations that
are necessary to do when the object is being created.

The self Parameter


 The self parameter is a reference to the current instance of the class, and is used to access
variables that belong to the class.
 It does not have to be named self, you can call it whatever you like, but it has to be the
first parameter of any function in the class

Part Meaning
def Define a method
__init__ Constructor method
self Refers to the current object
self.name = name Stores the name in the object
self.age = age Stores the age in the object

Example:
class Student:

def __init__(self, name):

self.name = name

Note: The __init_() function is called automatically every time the class is being used to create a
new object.
Note: The self parameter is a reference to the current instance of the class, and is used to access
variables that belong to the class.

Object
 An object is an instance of a class.
 It has real values assigned to class properties.

Example:
s1 = Student("Alice")

print(s1.name) # Output: Alice

Object Methods
Objects can also contain methods. Methods in objects are functions that belong to the object.

Example:
class Student:
def __init__(self, a, b):

self.name = a
self.rollno = b

def myfunc(self):
print("Hello my name is " + self.name)

s1 = Student("John", 36)
s1.myfunc()
Or
class Student:
def __init__(obj, name, rollno):
obj.name = name
obj.rollno = rollno
def myfunc(abc):
print("Hello my name is " + abc.name)

s1 = Student ("John", 36)


s1.myfunc()

Modify Object Properties


You can modify properties on objects like this:
p1.rollno = 40

Delete Object Properties


You can delete properties on objects by using the del keyword:
Del p1.rollno

The pass Statement


Class definitions cannot be empty, but if you for some reason have a class definition with no
content, put in the pass statement to avoid getting an error.
class Person:
pass

Using member function


Only create member function named disp()
class Person:
rno=15
def disp(a):
print(a.rno)
# Create an object
p1 = Person()
p1.disp()

Encapsulation
Encapsulation is one of the fundamental concepts in object-oriented programming (OOP). It
describes the bundling of data (attributes) and methods that operate on that data into a single
unit, usually a class. It also refers to restricting access to some of an object's components, which
helps prevent the accidental modification of data.
Key Features of Encapsulation in Python
1. Private and Protected Members:
o Public members: Accessible from anywhere (self.name)
o Protected members: Indicated by a single underscore (_name). Treated as
internal use only.
o Private members: Indicated by a double underscore (__name). Name mangled to
prevent access from outside the class directly.
2. Getter and Setter Methods:
o Used to read and update private attributes safely.

Example: Simple example of private and protected data members

Note: private data members are only accessed within the class

class encapsul:
_a=10 # protected member
__b=20 # private member
def show(self):
print("protected a = ",self._a)
print("private b = ",self.__b)
e=encapsul()
e.show()
print("outside of class protected member",e._a)
#print("outside of class private member",e.__b)
print("access -> outside of class private member",encapsul._encapsul__b)

Output:
protected a = 10
private b = 20
outside of class protected member 10
outside of class private member 20
Change -> outside of class private member 50
Encapsulation
Encapsulation in Python is a fundamental concept in object-oriented programming (OOP) that
involves bundling data (attributes) and methods (functions) that operate on that data within a
single unit, which is a class.
Example of Encapsulation:
class Student:
def __init__(self, name, age, grade):
self.name = name # Public attribute
self._age = age # Protected attribute
self.__grade = grade # Private attribute

# Getter for private attribute


def get_grade(self):
return self.__grade

# Setter for private attribute


def set_grade(self, new_grade):
if 0 <= new_grade <= 100:
self.__grade = new_grade
else:
print("Invalid grade. Must be between 0 and 100.")

# Method to display student info


def display_info(self):
print(f"Name: {self.name}")
print(f"Age: {self._age}")
print(f"Grade: {self.__grade}")

# Create a student object


student1 = Student("John Doe", 18, 85)

# Accessing public attribute


print("Public (Name):", student1.name)

# Accessing protected attribute (allowed, but not recommended)


print("Protected (Age):", student1._age)

# Trying to access private attribute directly (will fail)


# print(student1.__grade) # ❌ AttributeError

# Accessing private attribute via getter


print("Private (Grade):", student1.get_grade())

# Updating private attribute via setter


student1.set_grade(92)
print("Updated Grade:", student1.get_grade())

# Trying to set invalid grade


student1.set_grade(150) # ❌ Invalid grade
# Display all info
print("\nFull Student Info:")
student1.display_info()

output:
Public (Name): John Doe
Protected (Age): 18
Private (Grade): 85
Updated Grade: 92
Invalid grade. Must be between 0 and 100.

Output:
Full Student Info:
Name: John Doe
Age: 18
Grade: 92

Access specifiers in Python have an important role to play in securing data from unauthorized
access and in preventing it from being exploited.

A Class in Python has three types of access modifiers:


Public Access Modifier: Theoretically, public methods and fields can be accessed directly by
any class. By default all variables are public.
Protected Access Modifier: Theoretically, protected methods and fields can be accessed within
the same class it is declared and its subclass.
Private Access Modifier: Theoretically, private methods and fields can be only accessed within
the same class it is declared.

Constructors and Destructors:

The __init__() Function (Constructors)

 A constructor is a special method used to initialize objects when they are created from a
class. It is automatically invoked when a new instance of a class is created. The primary
purpose of a constructor is to set up the initial state of the object by assigning values to its
attributes or performing any necessary setup operations.
class stud:
def __init__(a, name,rno):
a.name=name
a.rno=rno
s1=stud("abc",25)
print(s1.name)
print(s1.rno)

Output:
abc
25

The __del__() Function (Destructors)


 A destructor is a special method named __del__() that is called when an object is about to
be destroyed or deleted.
 Unlike constructors (__init__), which are called when an object is created, destructors are
invoked to perform cleanup operations before an object is removed from memory.
class MyClass:
def __init__(self, name):
self.name = name
print(f"Object {self.name} created")

def __del__(self):
print(f"Object {self.name} is being destroyed")

# Example usage
obj = MyClass("Test")
del obj # Manually deletes the object, triggers __del__()

Output:
Object Test created
Object Test is being destroyed

Inheritance:

Inheritance is a basic idea in object-oriented programming (OOP). It is used to inherit the


properties and behavior of one class to another. The class that inherits another class is called
a child class and the class that gets inherited is called a base class or parent class.

Inheritance comes into picture when a new class possesses 'IS A' relationship with an existing
class. For example, Car IS a vehicle, Bus IS a vehicle, Bike IS also a vehicle. Here, Vehicle is
the parent class, whereas car, bus and bike are the child classes.

1. Parent Class:
 This is the base class from which other classes inherit.
 It contains attributes and methods that the child class can reuse.

2. Child Class:
 This is the derived class that inherits from the parent class.
 The syntax for inheritance is class ChildClass (ParentClass).
 The child class automatically gets all attributes and methods of the parent class unless
overridden.
 Syntax for Inheriting child class: class ChildClass(ParentClass):

Creating a Parent Class


In object-oriented programming, a parent class (also known as a base class) defines common
attributes and methods that can be inherited by other classes.

Creating a Child Class


A child class (also known as a subclass) is a class that inherits properties and methods from its
parent class. The child class can also introduce additional attributes and methods, or even
override the ones inherited from the parent.

Syntax for Inheritance


class ParentClass:
# Parent class code here

class ChildClass(ParentClass):
# Child class code here

This helps you:

 Reuse code instead of writing the same code again


 Organize your code better
 Build relationships between classes (like how a dog is a type of animal)

For example, if you have a parent class called Animal, a child class like Dog can inherit from it
and get all the basic features of an animal, like eating or sleeping. Then you can add special
features just for dogs.

Use of super() in inheritance:


 super() is used to call methods from the parent class inside a child (derived) class.
 super() lets the child class access the parent class’s methods or constructor, avoiding
code repetition.

Types of inheritance in Python:

 Single: One parent, one child


 Multiple: Child inherits from multiple parents
 Multilevel: Child → Parent → Grandparent
 Hierarchical: One parent, multiple children
 Hybrid: Combination of the above

Single Inheritance
This type of inheritance where a child class (also known as a derived class or subclass) inherits
attributes and methods from only one parent class (also known as a base class)

Example 1:
# parent class
class Parent:
def parentMethod(self):
print ("Calling parent method")

# child class
class Child(Parent):
def childMethod(self):
print ("Calling child method")

# instance of child
c = Child()
# calling method of child class
c.childMethod()
# calling method of parent class
c.parentMethod()

Output:
Calling child method
Calling parent method

Example 2:
# A Python program to demonstrate Single inheritance
#Base Class
class Person():

# Constructor
def __init__(self, name, id):
self.name = name
self.id = id

# To check if this person is an employee


def Display(self):
print(self.name, self.id)

#Derived Class
class Emp(Person):

def Print(self):
print("Emp class called")
print(self.name, self.id)

#Creae Object
Emp_details = Emp("ABC", 101)
# calling parent class function
print("Call base class method - Display")
Emp_details.Display()

# Calling child class function


print("Call Derived class method - print")
Emp_details.Print()

Output:
Call base class method - Display
Parent Class method
ABC 101
Call Derived class method - print
Emp class called
ABC 101

Multiple Inheritance
In this inheritance a class can inherit attributes and methods from more than one parent
class. This allows a child class to combine functionalities from multiple sources

super() Function
class Parent:
def show(self):
print("This is the parent class.")

class Child(Parent):
def show(self):
super().show() # Calls Parent's show()
print("This is the child class.")

c = Child()
c.show()

Output:
This is the parent class.
This is the child class.

Multiple (User define input- using method)


# Parent class 1
class Person:
def display_person_info(self):
print(f"Name: {self.name}, Age: {self.age}")

# Parent class 2
class StudentDetails:
def display_student_info(self):
print(f"Student ID: {self.student_id}, Course: {self.course}")
# Child class inheriting from both Person and StudentDetails
class Student(Person, StudentDetails):
def set_details(self):
self.name = input("Enter name: ")
self.age = int(input("Enter age: "))
self.student_id = input("Enter student ID: ")
self.course = input("Enter course: ")

def display(self):
self.display_person_info()
self.display_student_info()

# Create a Student object


student = Student()

# Set attributes using user input


student.set_details()

# Display student info


student.display()

Output:
Enter name: Pooja
Enter age: 25
Enter student ID: 101
Enter course: BCA
Name: Pooja, Age: 25
Student ID: 101, Course: BCA

Hierarchical Inheritance Concept:


 One base class and multiple derived classes inherit from the same base class.
# Base Class
class Student:
def __init__(self, name, roll_no):
self.name = name
self.roll_no = roll_no

def display_student_info(self):
print(f"Name: {self.name}")
print(f"Roll Number: {self.roll_no}")

# Derived Class 1
class AcademicStudent(Student):
def __init__(self, name, roll_no, marks):
super().__init__(name, roll_no)
self.marks = marks

def display_academic_info(self):
self.display_student_info()
print(f"Academic Marks: {self.marks}")

# Derived Class 2
class SportsStudent(Student):
def __init__(self, name, roll_no, sport):
super().__init__(name, roll_no)
self.sport = sport

def display_sports_info(self):
self.display_student_info()
print(f"Sport: {self.sport}")

# Using the classes


academic = AcademicStudent("ABC", "15", 50)
sports = SportsStudent("PQR", "20", "Basketball")

print("=== Academic Student ===")


academic.display_academic_info()

print("\n=== Sports Student ===")


sports.display_sports_info()

Output:
=== Academic Student ===
Name: ABC
Roll Number: 15
Academic Marks: 50

=== Sports Student ===


Name: PQR
Roll Number: 20
Sport: Basketball

Multilevel Inheritance Concept:

 A class is derived from another derived class (Intermediate base class) that is Multilevel
inheritance.
 For example:
Base -> Derived1 -> Derived2

Example: Student → Academic_Student → Result


#Multi level inheritance
# Base Class
class Student:
def __init__(self, name, roll_no):
self.name = name
self.roll_no = roll_no
def display_student_info(self):
print(f"Name: {self.name}")
print(f"Roll Number: {self.roll_no}")

# Derived Class 1
class AcademicStudent(Student):
def __init__(self, name, roll_no, subject):
super().__init__(name, roll_no)
self.subject = subject

def display_academic_info(self):
print(f"Subject: {self.subject}")

# Derived Class 2 (Multilevel)


class Result(AcademicStudent):
def __init__(self, name, roll_no, subject, marks):
super().__init__(name, roll_no, subject)
self.marks = marks

def display_result(self):
self.display_student_info()
self.display_academic_info()
print(f"Marks: {self.marks}")

# Using the multilevel inherited class


student_result = Result("ABC", "S001", "Mathematics", 88)

print("=== Student Result ===")


student_result.display_result()

Output:
=== Student Result ===
Name: ABC
Roll Number: S001
Subject: Mathematics
Marks: 88

Hybrid Inheritance:
Hybrid inheritance is a combination of more than one type of inheritance. For example, it can
include a mix of multiple and hierarchical inheritance.
# Base class
class Person:
def __init__(self, name):
self.name = name

def display_name(self):
print("Name:", self.name)
# Derived class 1 (single inheritance)
class Student(Person):
def __init__(self, name, student_id):
super().__init__(name)
self.student_id = student_id

def display_student_id(self):
print("Student ID:", self.student_id)

# Derived class 2 (hierarchical inheritance)


class Marks(Student):
def __init__(self, name, student_id, marks):
super().__init__(name, student_id)
self.marks = marks

def display_marks(self):
print("Marks:", self.marks)

# Another class using multiple inheritance


class Sports:
def __init__(self, sport_name):
self.sport_name = sport_name

def display_sport(self):
print("Sport:", self.sport_name)

# Final derived class using hybrid inheritance (Marks + Sports)


class Result(Marks, Sports):
def __init__(self, name, student_id, marks, sport_name):
Marks.__init__(self, name, student_id, marks)
Sports.__init__(self, sport_name)

def display_result(self):
self.display_name()
self.display_student_id()
self.display_marks()
self.display_sport()

# Create object
r1 = Result("Alice", "S101", 88, "Basketball")
r1.display_result()

Output:
Name: Alice
Student ID: S101
Marks: 88
Sport: Basketball

Polymorphism
The word "polymorphism" means "many forms", and in programming it refers to
methods/functions/operators with the same name that can be executed on many objects or
classes.
Types of Polymorphism

Method Overloading Operator Overloading

Method Overloading in Python


Method overloading means having multiple methods in the same class with the same name but
different parameters (number or type).

Note: Python does not support true method overloading like Java or C++. The last defined
method with the same name will override the previous ones.

Instead, you can simulate method overloading using:


 Default arguments
 Variable-length arguments (*args, **kwargs)

Example 1:
class Cat:
def sound(self):
return "Meow"

class Dog:
def sound(self):
return "Woof"

# Polymorphic function
def make_sound(animal):
print(animal.sound())
c = Cat()
d = Dog()

make_sound(c) # Meow
make_sound(d) # Woof

Output:
Meow
Woof

OR
#Polymorphism with Class Methods
class Student:
def info(self):
print("I am a student.")

class Teacher:
def info(self):
print("I am a teacher.")

# Iterate over different objects


for person in (Student(), Teacher()):
person.info()

Output:
I am a student.
I am a teacher.

Example 2:
class Student:
def show_info(self):
name = "ABC"
grade = "N/A"
print( f"Name: {name}, Grade: {grade}")

class ScienceStudent:
def show_info(self):
name = "PQR"
grade = "A"
print(f"Name: {name}, Grade: {grade}")

class CommerceStudent:
def show_info(self):
name = "XYZ"
grade = "B"
print(f"Name: {name}, Grade: {grade}")
# Polymorphism in action
def print_student_details(student):
student.show_info()

# Objects
s1 = Student()
s2 = ScienceStudent()
s3 = CommerceStudent()

# Call same function for different objects


print_student_details(s1)
print_student_details(s2)
print_student_details(s3)

Output:
Name: ABC, Grade: N/A
Name: PQR, Grade: A
Name: XYZ, Grade: B

Example 3: Simulated method overloading


class Student:
def get_details(self, name=None, student_id=None):
if name is not None and student_id is not None:
print(f"Name: {name}, ID: {student_id}")
elif name is not None:
print(f"Name: {name}")
else:
print("No details provided")

# Using the class


student = Student()

# Call the same method with different arguments


student.get_details("Alice", "S101") # With name and ID
student.get_details("Bob") # With only name
student.get_details() # No details

Operator Overloading:

Operator overloading allows custom behavior for standard operators (like `+`, `-`, `*`, etc.) when
used with user-defined objects (like classes).

Python uses special methods (also called magic methods) to handle operator overloading.

These methods start and end with double underscores: `__add__`, `__sub__`, `__mul__`, etc.

+ __add__ a+b
- __sub__ a-b
* __mul__ a*b
/ __truediv__ a/b
== __eq__ a==b
< __lt__ a<b
Str() __str__() Str(a)

+ Operator Example (__add__):

__add__ () is a special method used to define behavior of the + operator.

When s1 + s2 are executed, Python internally calls s1.__add__ (s2).

This is operator overloading, a type of polymorphism where the same


Operator works differently based on operands.

Example 1 (+ operator overloading):


class Student:
def __init__(self, name, marks):
self.name = name
self.marks = marks

# Operator overloading for +


def __add__(self, other):
return self.marks + other.marks

# Create two student objects


s1 = Student("ABC", 80)
s2 = Student("PQR", 90)

# Add their marks using overloaded +


total = s1 + s2

print("Total marks of both students:", total)

Output:
Total marks of both students: 170

Example 2 (+ operator overloading):


class Student:
def __init__(self, name, marks):
self.name = name
self.marks = marks

def __add__(self, other):


if isinstance(other, Student):
return self.marks + other.marks
elif isinstance(other, str):
return self.name + other
elif isinstance(other, (int, float)):
return self.marks + other
else:
return NotImplemented

# Create student objects


s1 = Student("ABC", 85)
s2 = Student("PQR", 90)

# Add two students' marks


print("Total marks:", s1 + s2) # 85 + 90 = 175

# Add name with string


print("Full name:", s1 + " XYZ") # "ABC" + " XYZ"

# Add marks with number


print("Updated marks:", s1 + 5.5) # 85 + 5 = 90

Output:
Total marks: 175
Full name: ABC XYZ
Updated marks: 90.5

Explanation:
isinstance() is a built-in Python function used to check the type of a variable or object at runtime.

isinstance(object, class_or_tuple)
object: The variable you want to check.

class_or_tuple: The type (or tuple of types) you want to check against.
isinstance()-
You use it to safely perform operations based on an object’s type.
This is especially useful when overloading operators or writing functions that behave differently
based on input types.

isinstance(other, Student) → checks if the operand is another Student.

isinstance(other, str) → allows name + string.

isinstance(other, (int, float)) → allows adding numeric values to marks.

NotImplemented → tells Python this operation isn’t supported for other types.

Example 3 (= Operator Example):


class Student:
def __init__(self, name, marks):
self.name = name
self.marks = marks

def __eq__(self, other):


return self.marks == other.marks

# Create student objects


s1 = Student("Alice", 85)
s2 = Student("Bob", 85)
s3 = Student("Charlie", 90)

# Compare students using ==


# s1.__eq__(s2)
print(s1 == s2) # True, because their marks are the same
print(s1 == s3) # False, different marks

Output:
True
False

Example 4 (-Operator Example):


class Student:
def __init__(self, name, marks):
self.name = name
self.marks = marks

def __sub__(self, other):


return self.marks - other.marks

# Create student objects


s1 = Student("Alice", 90)
s2 = Student("Bob", 75)

# Subtract marks using overloaded -


result = s1 - s2

print("Difference in marks:", result)

Output:
Difference in marks: 15

Method Overriding in Python

Method overriding means redefining a method in a subclass that already exists in the parent
class.

The child class provides a specific implementation of a method that is already defined in its
parent class.
Key Differences Method Overloading and Method Overriding:
Feature Method Overloading Method Overriding
Definition Same method name, different parameters Redefining a method in child class
Scope Same class Parent and child classes
Python Support Not directly supported Fully supported
Flexibility Simulated using default/variable arguments Done by redefining the method
Purpose Code flexibility in method calls Customizing inherited behavior

Run Time Polymorphism:


Run-time polymorphism in Python happens when a child class overrides a method from its
parent class, and the version that runs depends on the object used at run time.
#Run time Poly
# Base class
class Student:
def get_details(self):
print("General student information.")

# Subclass 1
class Undergraduate(Student):
def get_details(self):
print("Undergraduate student: Enrolled in bachelor's program.")

# Subclass 2
class Graduate(Student):
def get_details(self):
print("Graduate student: Working on master's")

# Function demonstrating polymorphism


def show_student_info(stud):
stud.get_details()

# Create objects of different subclasses


student1 = Undergraduate()
student2 = Graduate()

# Call the same method on different objects (runtime polymorphism)


show_student_info(student1) # Output depends on actual object
show_student_info(student2)

Output:
Undergraduate student: Enrolled in bachelor's program.
Graduate student: Working on master's

Example of Runtime Polymorphism with concept of Constructor and


Inheritance.
#Constructor+Inheritance+Polymorphisam = Run time poly
# Base class
class Student:
def __init__(self, name, student_id):
self.name = name
self.student_id = student_id

def get_details(self):
return f"Name: {self.name}, ID: {self.student_id}"

# Derived class 1
class UndergraduateStudent(Student):
def __init__(self, name, student_id, major):
super().__init__(name, student_id)
self.major = major

def get_details(self): # Overriding the base method


return f"Undergraduate Student: {self.name}, ID: {self.student_id}, Major: {self.major}"

# Derived class 2
class GraduateStudent(Student):
def __init__(self, name, student_id, thesis_topic):
super().__init__(name, student_id)
self.thesis_topic = thesis_topic

def get_details(self): # Overriding the base method


return f"Graduate Student: {self.name}, ID: {self.student_id}, Thesis: {self.thesis_topic}"

# Polymorphic function
def print_student_info(student):
print(student.get_details())

# Using the classes


student1 = UndergraduateStudent("ABC", "UG123", "Computer Science")
student2 = GraduateStudent("PQR", "GR456", "Artificial Intelligence")

# Demonstrating Polymorphism
print_student_info(student1)
print_student_info(student2)

Output:
Undergraduate Student: ABC, ID: UG123, Major: Computer Science
Graduate Student: PQR, ID: GR456, Thesis: Artificial Intelligence

Introduction to Data Structures in Python

A data structure is a way of organizing, managing, and storing data so that it can be accessed and
modified efficiently.
Data Structures are a way of organizing data so that it can be accessed more efficiently
depending upon the situation

Python provides several built-in data structures that are widely used for solving real-world
problems.

Built-in Data Structures in Python that mansion in syllabus is lists, sets, tuples, dictionaries.

List

Python Lists are just like the arrays, declared in other languages which is an ordered collection of
data. It is very flexible as the items in a list do not need to be of the same type.

The implementation of Python List is similar to Vectors in C++ or ArrayList in JAVA. The
costly operation is inserting or deleting the element from the beginning of the List as all the
elements are needed to be shifted. Insertion and deletion at the end of the list can also become
costly in the case where the pre allocated memory becomes full.

We can create a list in python as shown below.

 A list is a collection of items (elements) which is ordered, mutable (can be changed),


and allows duplicate values.
 Lists are defined using square brackets [ ].
 The items in a Python list need not be of the same data type.
 List is an ordered collection of items. Each item in a list has a unique position index,
starting from 0.

Note: A Python list is mutable. Any item from the list can be accessed using its index, and can
be modified. One or more objects from the list can be removed or added. A list may have same
item at more than one index positions.

students = ["Pooja", "Palak", "Pinakin"]

list1 = ["Rohan", "Physics", 21, 69.75]

list2 = [1, 2, 3, 4, 5]

list3 = ["a", "b", "c", "d"]

list4 = [25.50, True, -55, 1+2j]

Accessing Values in Lists:


Use indexing to access elements. Index starts at 0.
print(students[0]) # Output: Pooja

print(students[2]) # Output: Pinakin


Updating Lists:
You can change an element by assigning a new value to its index.
students[1] = "David"

print(students) # Output: [' Pooja ', 'David', ' Pinakin ']

Delete List Elements


Use del, remove(), or pop() to delete items.
del students[0] # Deletes by index

students.remove("David") # Deletes by value

students.pop() # Deletes last element

Python List Operations

Operation Description Example


`+` (concatenation) Joins two lists `[1,2] + [3,4]` → `[1,2,3,4]`
` *` (repetition) Repeats the list `[1,2]*2` → `[1,2,1,2]`
`in` Checks if item exists `2 in [1,2,3]` → `True`
`len()` Returns number of items `len(students)` → `3`
`min()` / `max() Smallest/largest item `min([5,2,9])` → `2`
`list()` Converts to list `list("abc")` → `['a','b','c']`

Indexing in Lists
Positive index: Starts from 0
Negative index: Starts from -1 (last element)

marks = [90, 85, 70, 95]

print(marks[-1]) # Output: 95

Slicing Lists
Syntax: list[start:stop:step]
subjects = ["Math", "Science", "English", "History"]

print(subjects[1:3]) # ['Science', 'English']

print(subjects[:2]) # ['Math', 'Science']

print(subjects[::2]) # ['Math', 'English']

Matrix (List of Lists)


A matrix can be represented as a list of lists.
# Marks of 3 students in 2 subjects
marks_matrix = [

[85, 90], # Student 1

[78, 88], # Student 2

[92, 95] # Student 3

# Access mark of student 2 in subject 1

print(marks_matrix[1][0]) # Output: 78

Python List Methods


Method Description ❌ Example
append(x) Adds item x at the end students.append("Eve")
insert(i, x) Inserts x at index i students.insert(1, "Liam")
remove(x) Removes first occurrence of x students.remove("Alice")
pop(i) Removes and returns item at index i (last by default) students.pop()
sort() Sorts the list in ascending order marks.sort()
reverse() Reverses the list marks.reverse()
count(x) Counts how many times x occurs marks.count(85)
index(x) Returns index of first occurrence of x marks.index(90)
clear() Removes all elements students.clear()
copy() Returns a shallow copy new_list = students.copy()

Application Areas:

 Storing ordered collections (e.g., lines in a text file, database rows)


 Queues or stacks (with .pop() or .append())
 Iterative processing (e.g., looping over datasets)

# Student List Demo - All List Operations

# 1. Creating a list of student names


students = ["Alice", "Bob", "Charlie", "David"]
print("Original Student List:", students)

# 2. Accessing elements using indexing


print("First student:", students[0])
print("Last student:", students[-1])

# 3. Updating a student's name


students[1] = "Ben"
print("Updated Student List:", students)

# 4. Adding a new student using append


students.append("Eve")
print("After Appending 'Eve':", students)

# 5. Inserting a student at a specific position


students.insert(2, "Liam")
print("After Inserting 'Liam' at index 2:", students)

# 6. Removing a student by name


students.remove("Charlie")
print("After Removing 'Charlie':", students)

# 7. Removing the last student using pop


removed_student = students.pop()
print("After Popping Last Student:", students)
print("Removed Student:", removed_student)

# 8. List operations
new_students = ["Grace", "Hannah"]
combined = students + new_students
print("Combined List:", combined)

repeated = new_students * 2
print("Repeated List:", repeated)

# 9. Slicing
print("Sliced [1:3]:", students[1:3])
print("Every second student:", students[::2])

# 10. Length, Min, Max


marks = [85, 92, 78, 95, 90]
print("Marks List:", marks)
print("Total Students:", len(students))
print("Highest Mark:", max(marks))
print("Lowest Mark:", min(marks))

# 11. Matrix (list of lists) - Marks for each student in 3 subjects


student_marks = [
[85, 90, 88], # Alice
[78, 85, 80], # Ben
[92, 94, 96], # Liam
[88, 86, 90] # David
]
print("Marks of Liam in subject 2:", student_marks[2][1]) # 94

# 12. Sorting and reversing marks


marks.sort()
print("Sorted Marks:", marks)

marks.reverse()
print("Reversed Marks:", marks)

# 13. Count and index


print("Count of 85 in marks:", marks.count(85))
print("Index of 90 in marks:", marks.index(90))

# 14. Copy and clear


backup_students = students.copy()
students.clear()
print("Cleared Student List:", students)
print("Backup Student List:", backup_students)

Output:
Original Student List: ['Alice', 'Bob', 'Charlie', 'David']
First student: Alice
Last student: David
Updated Student List: ['Alice', 'Ben', 'Charlie', 'David']
After Appending 'Eve': ['Alice', 'Ben', 'Charlie', 'David', 'Eve']
After Inserting 'Liam' at index 2: ['Alice', 'Ben', 'Liam', 'Charlie', 'David', 'Eve']
After Removing 'Charlie': ['Alice', 'Ben', 'Liam', 'David', 'Eve']
After Popping Last Student: ['Alice', 'Ben', 'Liam', 'David']
Removed Student: Eve
Combined List: ['Alice', 'Ben', 'Liam', 'David', 'Grace', 'Hannah']
Repeated List: ['Grace', 'Hannah', 'Grace', 'Hannah']
Sliced [1:3]: ['Ben', 'Liam']
Every second student: ['Alice', 'Liam']
Marks List: [85, 92, 78, 95, 90]
Total Students: 4
Highest Mark: 95
Lowest Mark: 78
Marks of Liam in subject 2: 94
Sorted Marks: [78, 85, 90, 92, 95]
Reversed Marks: [95, 92, 90, 85, 78]
Count of 85 in marks: 1
Index of 90 in marks: 2
Cleared Student List: []
Backup Student List: ['Alice', 'Ben', 'Liam', 'David']

Tuple

Python Tuples are similar to lists, but they are immutable, meaning their elements cannot be
changed once assigned. Tuples are ordered collections that allow duplicate values and can store
different data types.

 Ordered, immutable(unable to be changed) , allows duplicate elements.


 Defined using parentheses ().

coordinates = (10.5, 20.3)


print(coordinates[0]) # 10.5

Key Characteristics of Tuples:


 A tuple is an ordered collection of items.
 Tuples are immutable (cannot be changed after creation).
 Defined using parentheses ().
 Can contain elements of different data types.
 Support duplicate values.
 Elements are accessed by index, starting from 0.

Creating a Tuple:
tuple1 = (10, 20, 30)

tuple2 = ("Alice", "Bob", "Charlie")

tuple3 = (25.5, True, "Hello", 1+2j)

tuple4 = () # Empty tuple

tuple5 = (5,) # Single element tuple (comma required)

Accessing Tuple Elements:


print(tuple2[0]) # Output: Alice

print(tuple3[-1]) # Output: (1+2j)

Tuple is Immutable:
tuple1[1] = 40 # ❌ Error: Tuples cannot be modified

Tuple Operations:
Operation Description Example Output
+ Concatenation (1, 2) + (3, 4) (1, 2, 3,
4)
* Repetition (1, 2) * 2 (1, 2, 1,
2)
in Membership test 3 in (1, 2, 3) True
len() Length of tuple len(tuple1) 3
min() Minimum element (comparable types only) min((4, 2, 7)) 2
Max() Maximum element max((4, 2, 7)) 7
tuple() Convert to tuple tuple([1, 2, (1, 2, 3)
3])

Slicing Tuples:
tuple1 = (10, 20, 30, 40, 50)

print(tuple1[1:4]) # (20, 30, 40)

print(tuple1[:3]) # (10, 20, 30)


print(tuple1[::2]) # (10, 30, 50)

Nested Tuples (Tuples inside Tuples):


nested = ((1, 2), (3, 4), (5, 6))

print(nested[1]) # (3, 4)

print(nested[1][0]) #3

Tuple Packing and Unpacking:


# Packing

person = ("John", 25, "Engineer")

# Unpacking

name, age, job = person

print(name) # John

print(age) # 25

print(job) # Engineer

Tuple Methods:
Method Description Example
.count(x) Returns the count of value x t.count(2) → 2
.index(x) Returns index of first x t.index(4) → 2

t = (1, 2, 4, 2, 5)

print(t.count(2)) # Output: 2

print(t.index(4)) # Output: 2

Application Areas:
 Fixed data values (e.g., coordinates, RGB color codes)
 Keys in dictionaries (if tuple is immutable)
 Data integrity (e.g., database rows that shouldn't be modified)
 Return multiple values from a function

Looping Through Tuples


Tuples are iterable, so you can use loops (like for and while) to go through their elements.

Using for Loop:


colors = ("red", "green", "blue")
for color in colors:
print(color)

Output:
red
green
blue

Using for Loop with range() and Indexing:


fruits = ("apple", "banana", "mango")
for i in range(len(fruits)):
print(fruits[i])

Output:
apple
banana
mango

Using while Loop:


numbers = (10, 20, 30, 40)

i=0

while i < len(numbers):

print(numbers[i])

i += 1//i=i+1

Output:
10
20
30
40

Loop with Tuple Unpacking:


students = (("John", 20), ("Alice", 22), ("Bob", 19))

for name, age in students:

print(name, "is", age, "years old.")

Output:
John is 20 years old.

Alice is 22 years old.

Bob is 19 years old.


Enumerate() with Tuples:
Get both index and value during loop.
animals = ("cat", "dog", "elephant")

for index, animal in enumerate(animals):

print(index, ":", animal)

Output:
0 : cat

1 : dog

2 : elephant

Comparing Tuples

Tuples are compared element by element from left to right.

print((1, 2, 3) < (1, 2, 4)) # Output: True

print((5, 1) > (4, 9)) # Output: True

# 1. Creating Tuples
tuple1 = (10, 20, 30)
tuple2 = ("Alice", "Bob", "Charlie")
tuple3 = (25.5, True, "Hello", 1+2j)
tuple4 = () # Empty tuple
tuple5 = (5,) # Single-element tuple

# 2. Accessing Tuple Elements


print(tuple2[0]) # Output: Alice
print(tuple3[-1]) # Output: (1+2j)

# 3. Tuple is Immutable
# tuple1[1] = 40 # ❌ This will raise TypeError

# 4. Tuple Operations
print((1, 2) + (3, 4)) # Output: (1, 2, 3, 4)
print((1, 2) * 2) # Output: (1, 2, 1, 2)
print(3 in (1, 2, 3)) # Output: True
print(len(tuple1)) # Output: 3
print(min((4, 2, 7))) # Output: 2
print(max((4, 2, 7))) # Output: 7
print(tuple([1, 2, 3])) # Output: (1, 2, 3)

# 5. Slicing Tuples
t = (10, 20, 30, 40, 50)
print(t[1:4]) # Output: (20, 30, 40)
print(t[:3]) # Output: (10, 20, 30)
print(t[::2]) # Output: (10, 30, 50)

# 6. Nested Tuples
nested = ((1, 2), (3, 4), (5, 6))
print(nested[1][0]) # Output: 3

# 7. Tuple Packing and Unpacking


person = ("John", 25, "Engineer")
name, age, job = person
print(name, age, job) # Output: John 25 Engineer

# 8. Tuple Methods
t = (1, 2, 4, 2, 5)
print(t.count(2)) # Output: 2
print(t.index(4)) # Output: 2

# 9. Looping Through Tuples


colors = ("red", "green", "blue")
for color in colors:
print(color)

for i in range(len(colors)):
print(colors[i])

i=0
while i < len(colors):
print(colors[i])
i += 1 #i=i+1

students = (("John", 20), ("Alice", 22), ("Bob", 19))


for name, age in students:
print(name, "is", age, "years old.")

for index, animal in enumerate(("cat", "dog", "elephant")):


print(index, ":", animal)

# 11. Comparing Tuples


print((1, 2, 3) < (1, 2, 4)) # Output: True
print((5, 1) > (4, 9)) # Output: True

# 12. Tuples in Functions


def get_name_and_age():
return ("Alice", 25)

name, age = get_name_and_age()


print(name) # Output: Alice
print(age) # Output: 25
# 13. Convert List <-> Tuple
lst = [1, 2, 3]
print(tuple(lst)) # Output: (1, 2, 3)

tup = (4, 5, 6)
print(list(tup)) # Output: [4, 5, 6]
Output:
Alice
(1+2j)
(1, 2, 3, 4)
(1, 2, 1, 2)
True
3
2
7
(1, 2, 3)
(20, 30, 40)
(10, 20, 30)
(10, 30, 50)
3
John 25 Engineer
2
2
red
green
blue
red
green
blue
red
green
blue
John is 20 years old.
Alice is 22 years old.
Bob is 19 years old.
0 : cat
1 : dog
2 : elephant
True
True
Alice
25
(1, 2, 3)
[4, 5, 6]
Python set

Python set is an unordered collection of multiple items having different datatypes. In Python,
sets are mutable, unindexed and do not contain duplicates. The order of elements in a set is not
preserved and can change.

Creating a Set in Python

In Python, the most basic and efficient method for creating a set is using curly braces.
Example:
set1 = {1, 2, 3, 4}

print(set1)

Using the set() function

Python Sets can be created by using the built-in set() function with an iterable object or a
sequence by placing the sequence inside curly braces, separated by a 'comma'.

Note: A Python set cannot contain mutable types such as lists or dictionaries, because they are
unhashable.

set1 = set()
print(set1)

set1 = set("ABCDEFGH")
print(set1)

# Creating a Set with the use of a List


set1 = set(["ABC", "PQR", "ABC"])
print(set1)

# Creating a Set with the use of a tuple


tup = ("ABC", "PQR", "ABC")
print(set(tup))

# Creating a Set with the use of a dictionary


d = {"ABC": 1, "PQR": 2, "XYZ": 3}
print(set(d))

Unordered, Unindexed and Mutability

In set, the order of elements is not guaranteed to be the same as the order in which they were
added. The output could vary each time we run the program. Also the duplicate items entered are
removed by itself.

Sets do not support indexing. Trying to access an element by index (set[0]) raises a TypeError.
We can add elements to the set using add(). We can remove elements from the set
using remove(). The set changes after these operations, demonstrating its mutability. However,
we cannot changes its items directly.

set1 = {3, 1, 4, 1, 5, 9, 2}

print(set1) # Output may vary: {1, 2, 3, 4, 5, 9}

# Unindexed: Accessing elements by index is not possible


# This will raise a TypeError
try:
print(set1[0])
except TypeError as e:
print(e)

Adding Elements to a Set in Python

We can add items to a set using add() method and update() method. add() method can be used to
add only a single item. To add multiple items we use update() method.

Example:
# Creating a set
set1 = {1, 2, 3}

# Add one item


set1.add(4)

# Add multiple items


set1.update([5, 6])

print(set1)

Accessing a Set in Python


We can loop through a set to access set items as set is unindexed and do not support accessing
elements by indexing. Also we can use in keyword which is membership operator to check if an
item exists in a set.
set1 = set(["ABC", "PQR", "ABC."])

# Accessing element using For loop


for i in set1:
print(i, end=" ")

# Checking the element# using in keyword


print("ABC" in set1)
# end=" ", it replaces the newline with a space, so all outputs from the print() calls in the
#loop appear on the same line, separated by spaces.

Explanation:
 This loop will print each item in the set. Since sets are unordered, the order of items
printed is not guaranteed.
 This code checks if the number 4 is in set1 and prints a corresponding message.

Removing Elements from the Set in Python

 We can remove an element from a set in Python using several methods: remove(),
discard() and pop(). Each method works slightly differently :
 Using remove() Method or discard() Method
 Using pop() Method
 Using clear() Method

Using remove() Method or discard() Method


remove() method removes a specified element from the set. If the element is not present in the
set, it raises a KeyError. discard() method also removes a specified element from the set. Unlike
remove(), if the element is not found, it does not raise an error.
# Using Remove Method
set1 = {1, 2, 3, 4, 5}
set1.remove(3)
print(set1)

# Attempting to remove an element that does not exist


try:
set1.remove(10)
except KeyError as e:
print("Error:", e)

# Using discard() Method


set1.discard(4)
print(set1)

# Attempting to discard an element that does not exist


set1.discard(10) # No error raised
print(set1)

Using pop() Method


pop() method removes and returns an arbitrary element from the set. This means we don't know
which element will be removed. If the set is empty, it raises a KeyError.

Note: If the set is unordered then there's no such way to determine which element is popped by
using the pop() function.
set1 = {1, 2, 3, 4, 5}
val = set1.pop()
print(val)
print(set1)

# Using pop on an empty set


set1.clear() # Clear the set to make it empty
try:
set1.pop()
except KeyError as e:
print("Error:", e)

Using clear() Method


clear() method removes all elements from the set, leaving it empty.
set1 = {1, 2, 3, 4, 5}
set1.clear()
print(set1)

Set Methods in Python


Function Description

add() Adds an element to a set

Removes an element from a set. If the element is not present in the


remove()
set, raise a KeyError

clear() Removes all elements form a set

copy() Returns a shallow copy of a set

Removes and returns an arbitrary set element. Raise KeyError if the


pop()
set is empty

update() Updates a set with the union of itself and others

union() Returns the union of sets in a new set

difference() Returns the difference of two or more sets as a new set

difference_update() Removes all elements of another set from this set

Removes an element from set if it is a member. (Do nothing if the


discard()
element is not in set)

intersection() Returns the intersection of two sets as a new set

intersection_update() Updates the set with the intersection of itself and another

isdisjoint() Returns True if two sets have a null intersection

issubset() Returns True if another set contains this set


Function Description

issuperset() Returns True if this set contains another set

symmetric_difference() Returns the symmetric difference of two sets as a new set

symmetric_difference_update() Updates a set with the symmetric difference of itself and another

Key Characteristics of set:

 Unordered: No guaranteed order of elements.


 Mutable: You can add or remove items after creation.
 No Duplicates: All elements must be unique.
 Defined using curly braces {} or the built-in set() function.

Creating a Set:
fruits = {"apple", "banana", "mango"}

empty_set = set() # NOT {} — this creates a dictionary

Mixed Data Types Allowed:


sample = {"hello", 42, 3.14, True}

Accessing Elements:

Unlike lists, you cannot access set items by index (e.g., set[0] is not allowed), because sets
are unordered.

You can iterate:


for fruit in fruits:

print(fruit)

Updating a Set:

Add Items:
fruits.add("orange") # Adds a single item

fruits.update(["kiwi", "melon"]) # Adds multiple items

Adding Duplicates:
fruits.add("apple") # Will not be added again

Deleting Items from a Set:


fruits.remove("banana") # Raises error if item not found
fruits.discard("banana") # Does NOT raise error

fruits.pop() # Removes a random item

fruits.clear() # Empties the set

del fruits # Deletes the set entirely

Set Operations:
Operation Description Example Output
union() or ` ` Combines `a
elements
intersection() or & Common elements a & b {...}
difference() or - Elements in a not in b a - b {...}
symmetric_difference() or ^ Elements in either, not both a ^ b {...}

a = {1, 2, 3}

b = {3, 4, 5}

print(a | b) # {1, 2, 3, 4, 5}

print(a & b) # {3}

print(a - b) # {1, 2}

print(a ^ b) # {1, 2, 4, 5}

Membership Test:
"apple" in fruits # True/False

Example:
# Set Demo - All Set Operations

# 1. Creating a set of student names (note: duplicates are automatically removed)


students = {"Alice", "Bob", "Charlie", "David"}
print("Original Student Set:", students)

# 2. Accessing elements (sets are unordered; no indexing, use a loop)


print("Iterating through students:")
for student in students:
print(student)

# 3. Updating is not direct — remove and add


students.discard("Bob")
students.add("Ben")
print("Updated Student Set (Replaced 'Bob' with 'Ben'):", students)
# 4. Adding a new student using add()
students.add("Eve")
print("After Adding 'Eve':", students)

# 5. Adding multiple students using update()


students.update(["Liam", "Grace"])
print("After Adding 'Liam' and 'Grace':", students)

# 6. Removing a student by name


students.remove("Charlie") # raises error if not found
print("After Removing 'Charlie':", students)

# 7. Removing a random student using pop()


removed_student = students.pop()
print("After Popping Random Student:", students)
print("Removed Student:", removed_student)

# 8. Set operations - union, intersection, difference


group_a = {"David", "Liam", "Sophia"}
group_b = {"Grace", "Sophia", "Olivia"}

print("Union of A and B:", group_a | group_b)


print("Intersection of A and B:", group_a & group_b)
print("Difference (A - B):", group_a - group_b)
print("Symmetric Difference:", group_a ^ group_b)

# 9. Membership testing
print("Is 'David' in students?", "David" in students)
print("Is 'Charlie' in students?", "Charlie" in students)

# 10. Length and clearing


print("Number of Students:", len(students))

# 11. Set of marks (numbers for min/max)


marks = {85, 92, 78, 95, 90}
print("Marks Set:", marks)
print("Highest Mark:", max(marks))
print("Lowest Mark:", min(marks))

# 12. Copying and clearing the set


backup_students = students.copy()
students.clear()
print("Cleared Student Set:", students)
print("Backup Student Set:", backup_students)

# 13. Set Comprehension (squares of even numbers from 0–10)


squares = {x*x for x in range(11) if x % 2 == 0}
print("Squares of Even Numbers:", squares)
# 14. Removing items safely
backup_students.discard("Eve") # No error if not present
print("After Discarding 'Eve':", backup_students)

Output:

Original Student Set: {'Bob', 'Charlie', 'Alice', 'David'}


Iterating through students:
Bob
Charlie
Alice
David
Updated Student Set (Replaced 'Bob' with 'Ben'): {'David', 'Charlie', 'Alice', 'Ben'}
After Adding 'Eve': {'David', 'Eve', 'Charlie', 'Alice', 'Ben'}
After Adding 'Liam' and 'Grace': {'David', 'Eve', 'Charlie', 'Alice', 'Ben', 'Liam', 'Grace'}
After Removing 'Charlie': {'David', 'Eve', 'Alice', 'Ben', 'Liam', 'Grace'}
After Popping Random Student: {'Eve', 'Alice', 'Ben', 'Liam', 'Grace'}
Removed Student: David
Union of A and B: {'Olivia', 'Liam', 'Sophia', 'Grace', 'David'}
Intersection of A and B: {'Sophia'}
Difference (A - B): {'Liam', 'David'}
Symmetric Difference: {'Olivia', 'David', 'Liam', 'Grace'}
Is 'David' in students? False
Is 'Charlie' in students? False
Number of Students: 5
Marks Set: {78, 85, 90, 92, 95}
Highest Mark: 95
Lowest Mark: 78
Cleared Student Set: set()
Backup Student Set: {'Liam', 'Grace', 'Eve', 'Alice', 'Ben'}
Squares of Even Numbers: {0, 64, 4, 36, 100, 16}
After Discarding 'Eve': {'Liam', 'Grace', 'Alice', 'Ben'}

Dictionaries in Python

Python dictionary is a data structure that stores the value in key: value pairs. Values in a
dictionary can be of any data type and can be duplicated, whereas keys can't be repeated and
must be immutable.

Example: Here, The data is stored in key:value pairs in dictionaries, which makes it easier to
find values.

How to Create a Dictionary


Dictionary can be created by placing a sequence of elements within curly {} braces, separated by
a 'comma'.
d = {1: 'ABC', 2: 'PQR', 3: 'XYZ'}
print(d)
Output:
{1: 'ABC', 2: 'PQR', 3: 'XYZ'}

d2 = dict(a = "ABC", b = "PQR", c = "XYZ")


print(d2)
Output:
{1: 'ABC', 2: 'PQR', 3: 'XYZ'}
{a: 'ABC', b: 'PQR', c: 'XYZ'}
 Dictionary keys are case sensitive: the same name but different cases of Key will be
treated distinctly.
 Keys must be immutable: This means keys can be strings, numbers or tuples but not
lists.
 Keys must be unique: Duplicate keys are not allowed and any duplicate key will
overwrite the previous value.
 Dictionary internally uses Hashing. Hence, operations like search, insert, delete can be
performed in Constant Time.

Accessing Dictionary Items


We can access a value from a dictionary by using the key within square brackets or get() method.
d = { "name": "ABC", 1: "Python", (5, 2): [1,2,4] }

# Access using key


print(d["name"])

# Access using get()


print(d.get("name"))

Output:
ABC
ABC

Adding and Updating Dictionary Items


We can add new key-value pairs or update existing keys by using assignment.
d = {1: 'ABC', 2: 'PQR', 3: 'XYZ'}

# Adding a new key-value pair


d["marks"] = 22

# Updating an existing value


d[1] = "Dictionary update"

print(d)

Output:
{1: 'ABC', 2: 'PQR', 3: 'XYZ', 'marks': 22}
{1: 'Dictionary update', 2: 'PQR', 3: 'XYZ', 'marks': 22}

Removing Dictionary Items


We can remove items from dictionary using the following methods:
 del: Removes an item by key.
 pop(): Removes an item by key and returns its value.
 clear(): Empties the dictionary.
 popitem(): Removes and returns the last key-value pair.

d = {1: 'ABC', 2: 'PQR', 3: 'XYZ', 'age':22}

# Using del to remove an item


del d["age"]
print(d)

# Using pop() to remove an item and return the value


val = d.pop(1)
print(val)
print(d)

# Using popitem to removes and returns


# the last key-value pair.
key, val = d.popitem()
print(f"Key: {key}, Value: {val}")

# Clear all items from the dictionary


d.clear()
print(d)
{1: 'ABC', 2: 'PQR', 3: 'XYZ'}
ABC
ABC
Key: age, Value: 22

Iterating Through a Dictionary


We can iterate over keys [using keys() method] , values [using values() method] or both
[using item() method] with a for loop.
d = {1: 'ABC', 2: 'Job', 'age':25, 'Sal':15000}

# Iterate over keys


for key in d:
print(key)

# Iterate over values


for value in d.values():
print(value)

# Iterate over key-value pairs


for key, value in d.items():
print(key, value)

Output:
1
2
age
Sal

ABC
Job
25
15000

1 ABC
2 Job
age 25
Sal 15000

d = {1: 'ABC', 2: 'PQR',


3: {'A': 'Hello', 'B': 'Hi', 'C': 'SDJ'}}

print(d)

Output:
{1: 'ABC', 2: 'PQR', 3: {'A': 'Hello', 'B': 'Hi', 'C': 'SDJ'}}

Copy method
SDJ = {
"Sub": "BCA",
"Year": "1St",
"Sem": 1
}
x=SDJ.copy()

print(x)

Output: {'Sub': 'BCA', 'Year': '1St', 'Sem': 1}

fromkeys() Method
Create a dictionary with 3 keys, all with the value 0:

x = ('key1', 'key2', 'key3')


y =0

exp = dict.fromkeys(x, y)

print(exp)

Output: {'key1': 0, 'key2': 0, 'key3': 0}


get() Method
SDJ = {
"Sub": "BCA",
"Year": "1St",
"Sem": 1
}

x=SDJ.get("Year")
print(x)

SDJ.items()
print(x)

DJ.keys()
print(x)

SDJ.update({"Year": "2nd"})
print(x)

SDJ.values()
print(x)

Output:
1St
dict_items([('Sub', 'BCA'), ('Year', '1St'), ('Sem', 1)])
dict_keys(['Sub', 'Year', 'Sem'])
{'Sub': 'BCA', 'Year': '2nd', 'Sem': 1}
dict_values(['BCA', '2nd', 1])

Methods
Method Description
clear() Removes all the elements from the dictionary
copy() Returns a copy of the dictionary
fromkeys() Returns a dictionary with the specified keys and value
get() Returns the value of the specified key
items() Returns a list containing a tuple for each key value pair
keys() Returns a list containing the dictionary's keys
pop() Removes the element with the specified key
popitem() Removes the last inserted key-value pair
setdefault() Returns the value of the specified key. If the key does not exist: insert the key,
with the specified value
update() Updates the dictionary with the specified key-value pairs
values() Returns a list of all the values in the dictionary
Difference table between Set, List, Tuple, and Dictionary in Python:

Feature List Tuple Set Dictionary


Syntax [1, 2, 3] (1, 2, 3) {1, 2, 3} {"a": 1, "b": 2}
Ordered Yes Yes No Yes (as of Python 3.7+)
Mutable Yes No Yes Yes
Duplicates Allowed Allowed Not allowed Keys not allowed, values
allowed
Indexing Yes Yes No By key, not index
Use case Ordered Fixed ordered Unique items Key-value pairs
collection data
Example use To-do list, stack Coordinates, Tags, sets of User profiles, settings,
constants IDs database row

Linear Vs Non-linear Data Structures: Key Differences

The data structure is a method of organizing and storing data and info in a way that a user can
utilize them efficiently. In computer science, the data structure is composed in a way that it
works with various algorithms. It has two broad categories:

o Linear Data Structure


o Non-Linear Data Structure

What is a Linear Data Structure?

It is a type of Data Structure where the data elements get linearly or sequentially arranged. The
elements attach themselves to their next and previous adjacents. The structure involves only a
single level- allowing a user to traverse all its components in a single run.

The linear data structure is very easy to understand and implement due to its linear arrangement,
for example, stack, array, linked list, queue, etc.

What Is a Non-Linear Data Structure?

It is a form of data structure where the data elements don’t stay arranged linearly or sequentially.
Since the data structure is non-linear, it does not involve a single level. Therefore, a user can’t
traverse all of its elements in a single run.

The non-linear data structure is not very easy to implement as compared to the linear data
structure. The utilization of computer memory is more efficient in this case, for example, graphs
and trees.
Difference table between Linear Data Structure and Non-Linear Data Structure
Feature Linear Data Structure Non-Linear Data Structure
Structure Type A structure where elements are A structure where elements are
arranged in a sequence or a arranged in a hierarchical or
linear order. interconnected manner

Arranged in a sequential order


Arranged in a hierarchical or network
format
Data Traversal One level at a time Multiple levels (branches)
Memory Usage Usually uses more memory May use memory efficiently
linearly
Examples Array, List, Stack, Queue Tree, Graph
Implementation Easy to implement and manage More complex to implement
Simplicity
Relationship Each element has a single Each element may be connected to
next/prev item multiple
Use Case Simple tasks like queueing, Complex tasks like searching,
storing list networking

Real-World Applications
Use Case Recommended Structure
To-do lists, sequences list
GPS coordinates, constant pairs tuple
Unique user IDs or tags set
User profiles, settings dict

 Python’s built-in data structures make it simple to handle different types of data
efficiently.
 Choose the right structure based on your needs:
o Use lists for ordered and mutable collections.
o Use tuples for fixed-size and immutable groupings.
o Use sets to eliminate duplicates and for fast membership checks.
o Use dictionaries for structured data and quick lookups.

You might also like