Introduction to Python
UNIT-I: Planning the Computer Program
Concept of problem solving, problem definition, program design, debugging, types of errors in programming, documentation. Techniques of problem solving: flowcharting, decision table, algorithms, structured programming concepts, programming methodologies viz. Top-down and bottom-up programming. Overview of programming: structure of a Python program, elements of Python memory.
UNIT-II: Introduction to Python
Python interpreter, using Python as calculator, Python shell, indentation. Atoms, identifiers and keywords, literals, strings, operators (arithmetic operator, relational operator, logical or Boolean operator, assignment operator, ternary operator, bitwise operator, increment or decrement operator). Creating Python programs: input and output statements, control statements (branching, looping, conditional statement, exit function, difference between break, continue and pass.), defining functions, default arguments, errors and exceptions. Iteration and recursion: conditional execution, alternative execution, nested conditionals, the return statement.
UNIT-III: Recursion and Strings
Recursion, stack diagrams for recursive functions, multiple assignment, the while statement, tables, two-dimensional tables. Strings and lists: string as a compound data type, length, traversal and the for loop, string slices, string comparison, a find function.
UNIT-IV: Lists and Object-Oriented Programming
Looping and counting, list values, accessing elements, list length, list membership, lists and for loops, list operations, list deletion. Cloning lists, nested lists. Object-oriented programming: introduction to classes, objects and methods, standard libraries.
UNIT-V: Data Structures and Searching/Sorting
Data structures: arrays, list, set, stacks and queues. Searching and sorting: linear and binary search, bubble, selection and insertion sorting.

UNIT-I: Planning the Computer Program

1. Concept of Problem Solving

Problem solving in programming involves analyzing a problem, designing a solution, implementing the solution, and testing the result. It is the first step in creating a working computer program.

2. Problem Definition

Clearly stating the problem helps define what inputs are required, what processing is needed, and what the expected output should be.

3. Program Design

Program design refers to planning the logical steps (algorithm) before coding. Techniques include using flowcharts, pseudocode, and structure diagrams.

4. Debugging and Types of Errors

Debugging is the process of finding and fixing errors in a program.

5. Documentation

Good documentation helps other programmers understand the code. It includes comments in the code, user manuals, and technical specifications.

6. Techniques of Problem Solving

Flowcharting

A graphical representation of the program logic using standard symbols like arrows, decision blocks, and processes.

Decision Table

It shows different conditions and corresponding actions in a table format for clarity in decision-making processes.

Algorithm

An algorithm is a step-by-step set of instructions to solve a specific problem.

    Algorithm to find the largest of two numbers:
    1. Start
    2. Input a, b
    3. If a > b then
         print a is largest
       else
         print b is largest
    4. Stop
                

Structured Programming Concepts

Encourages dividing a program into small, reusable modules or functions. It improves clarity and debugging.

7. Programming Methodologies

8. Overview of Python Programming

Python is a high-level, interpreted, general-purpose programming language with a focus on readability and simplicity.

9. Structure of a Python Program

    # Simple Python Program
    def greet():
        print("Hello, World!")
    
    greet()
                

10. Elements of Python

    # Variable and arithmetic operation
    x = 10
    y = 5
    print("Sum is:", x + y)
                

UNIT-II: Python Programming Basics

1. Python Interpreter

The Python interpreter reads and executes Python code line by line. It can be accessed via the command line or through an IDE like VS Code or IDLE.

2. Using Python as a Calculator

Python can be used for arithmetic operations directly in the shell.

    # Python as a calculator
    print(5 + 3)
    print(10 / 2)
    print(2 ** 3)
                

3. Python Shell

The interactive environment where you type code and see immediate output is called the Python shell.

4. Indentation

Python uses indentation (spaces/tabs) to define blocks of code. Incorrect indentation leads to errors.

    if 5 > 2:
        print("5 is greater than 2")  # Correct indentation
                

5. Atoms, Identifiers, and Keywords

6. Literals and Strings

Literals are fixed values in code, like numbers or text. Strings are enclosed in single or double quotes.

    name = "Python"
    age = 20
    print(name, "is", age, "years old")
                

7. Operators

    # Ternary operator example
    a = 5
    b = 10
    max_val = a if a > b else b
    print("Max is:", max_val)
                

8. Creating Python Programs

Python files end with .py. You can write code in any text editor or IDE and run it using the Python interpreter.

9. Input and Output Statements

    name = input("Enter your name: ")
    print("Hello", name)
                

10. Control Statements

Branching

    x = 10
    if x > 5:
        print("x is greater than 5")
    else:
        print("x is 5 or less")
                

Looping

    for i in range(5):
        print(i)
    
    # While loop
    i = 0
    while i < 3:
        print(i)
        i += 1
                

Exit Function

    import sys
    sys.exit()  # exits the program
                

Break, Continue, Pass

    for i in range(5):
        if i == 2:
            continue
        print(i)
                

11. Defining Functions

    def greet(name):
        print("Hello", name)
    
    greet("Alice")
                

Default Arguments

    def greet(name="Guest"):
        print("Hello", name)
    
    greet()
                

12. Errors and Exceptions

Exceptions can be handled using try-except blocks.

    try:
        x = int(input("Enter number: "))
    except ValueError:
        print("Invalid input!")
                

13. Iteration and Recursion

Conditional Execution

Execution depends on conditions using if-else.

Alternative Execution

Using if-elif-else for multiple conditions.

    x = 5
    if x > 10:
        print("Big")
    elif x == 5:
        print("Medium")
    else:
        print("Small")
                

Nested Conditionals

    x = 5
    if x > 0:
        if x < 10:
            print("x is between 0 and 10")
                

The return Statement

    def square(n):
        return n * n
    
    print(square(4))
                

Recursion

A function that calls itself.

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

UNIT-III: Recursion, Data Structures, and String/Lists

1. Recursion

Recursion occurs when a function calls itself in order to solve a problem. Each recursive call breaks the problem into simpler sub-problems.

    # Example of recursion: Factorial function
    def factorial(n):
        if n == 1:
            return 1
        else:
            return n * factorial(n - 1)
    
    print(factorial(5))
                

2. Stack Diagrams for Recursive Functions

Each recursive call is placed on the call stack. As the recursion progresses, a new stack frame is created. When the function reaches the base case, it starts unwinding and returns the result.

    # Factorial stack diagram representation:
    # factorial(5) → factorial(4) → factorial(3) → factorial(2) → factorial(1)
    # Unwinding: factorial(1) → factorial(2) → factorial(3) → factorial(4) → factorial(5)
                

3. Multiple Assignment

Multiple assignment allows you to assign values to multiple variables in a single statement.

    x, y, z = 10, 20, 30
    print(x, y, z)
                

4. The while Statement

The `while` loop repeatedly executes a block of code as long as a given condition is true.

    # Example of while loop
    x = 0
    while x < 5:
        print(x)
        x += 1
                

5. Tables

Tables are typically represented as lists of lists (two-dimensional arrays) in Python. These can be used to store data in rows and columns.

    # Creating a 2D table (list of lists)
    table = [[1, 2, 3], [4, 5, 6], [7, 8, 9]]
    
    # Accessing elements
    print(table[0][1])  # Output: 2
                

6. Two-Dimensional Tables

Two-dimensional tables can be useful for storing grids, matrices, or tabular data. You can access elements using two indices: one for the row and one for the column.

    # Example of accessing and modifying a 2D table
    matrix = [[1, 2], [3, 4]]
    matrix[0][1] = 99  # Change value
    print(matrix)  # Output: [[1, 99], [3, 4]]
                

7. Strings and Lists

String as a Compound Data Type

A string is a sequence of characters. It is a compound data type because it can hold multiple values (characters).

    # Example of a string as a compound data type
    s = "Hello"
    print(s[0])  # Output: H
                

String Length

Strings have a length, which can be found using the built-in `len()` function.

    s = "Python"
    print(len(s))  # Output: 6
                

Traversal Using a for Loop

You can use a `for` loop to traverse a string (or any iterable).

    s = "Python"
    for char in s:
        print(char)
                

String Slices

Strings can be sliced to get substrings. The slicing syntax is s[start:end].

    s = "Python"
    print(s[1:4])  # Output: yth
                

String Comparison

Strings can be compared using relational operators.

    s1 = "apple"
    s2 = "banana"
    print(s1 == s2)  # Output: False
    print(s1 < s2)  # Output: True
                

Find Function

The `find()` method returns the index of the first occurrence of a substring. If not found, it returns -1.

    s = "Python programming"
    index = s.find("programming")
    print(index)  # Output: 7
                

8. Lists

Creating Lists

Lists are ordered collections of items in Python. They can hold different data types.

    lst = [1, 2, 3, 4]
    print(lst)  # Output: [1, 2, 3, 4]
                

Accessing and Modifying Lists

You can access elements by index and modify them by assigning new values.

    lst[0] = 10
    print(lst)  # Output: [10, 2, 3, 4]
                

List Slicing

Lists can also be sliced to get sublists.

    lst = [1, 2, 3, 4, 5]
    print(lst[1:4])  # Output: [2, 3, 4]
                

List Methods

    lst = [1, 2, 3]
    lst.append(4)
    print(lst)  # Output: [1, 2, 3, 4]
                

UNIT-IV: Lists, Loops, and Object-Oriented Programming

1. Looping and Counting with Lists

Looping allows us to iterate over list elements. The `for` loop is commonly used for counting elements in a list, and can also be used to iterate through the list to perform specific operations.

    # Loop through a list and count the number of elements
    lst = [1, 2, 3, 4, 5]
    count = 0
    for item in lst:
        count += 1
    print("Total elements:", count)
                

2. Accessing List Elements

Each item in a list has an index, which can be used to access elements directly. Indexing starts at 0.

    # Accessing elements in a list
    lst = ['apple', 'banana', 'cherry']
    print(lst[0])  # Output: apple
    print(lst[1])  # Output: banana
    print(lst[2])  # Output: cherry
                

3. List Length

The `len()` function returns the number of elements in a list.

    # Find the length of a list
    lst = ['apple', 'banana', 'cherry']
    print(len(lst))  # Output: 3
                

4. List Membership

The `in` operator is used to check if an element is present in a list.

    # Check membership in a list
    lst = ['apple', 'banana', 'cherry']
    print('banana' in lst)  # Output: True
    print('orange' in lst)  # Output: False
                

5. Lists and For Loops

You can use `for` loops to iterate over a list and perform operations on each element.

    # Example of looping through a list
    lst = [10, 20, 30, 40]
    for item in lst:
        print(item * 2)
                

6. List Operations

Python provides various operations to manipulate lists, such as adding, removing, or modifying elements.

    # Adding elements to a list
    lst = [1, 2, 3]
    lst.append(4)
    lst.insert(1, 10)  # Insert at index 1
    print(lst)  # Output: [1, 10, 2, 3, 4]
    
    # Removing elements
    lst.remove(10)  # Removes the first occurrence of 10
    lst.pop()  # Removes the last element
    print(lst)  # Output: [1, 2, 3]
                

7. List Deletion

Elements in a list can be deleted using the `del` keyword or the `remove()` method.

    # Deleting elements from a list
    lst = [1, 2, 3, 4]
    del lst[1]  # Removes element at index 1
    print(lst)  # Output: [1, 3, 4]
                

8. Cloning Lists

Cloning a list allows you to create a new copy of the list. You can use slicing or the `copy()` method to clone a list.

    # Cloning a list
    lst = [1, 2, 3]
    cloned_lst = lst[:]  # Slicing method
    print(cloned_lst)  # Output: [1, 2, 3]
                
    # Alternatively, using the copy() method
    cloned_lst = lst.copy()
    print(cloned_lst)  # Output: [1, 2, 3]
                

9. Nested Lists

A nested list is a list within another list, allowing you to store more complex data structures.

    # Example of a nested list (list of lists)
    nested_lst = [[1, 2, 3], [4, 5, 6], [7, 8, 9]]
    
    # Accessing elements in a nested list
    print(nested_lst[0][1])  # Output: 2
    print(nested_lst[2][2])  # Output: 9
                

10. Object-Oriented Programming (OOP)

Introduction to Classes, Objects, and Methods

OOP is a programming paradigm based on the concept of objects. Objects are instances of classes, and methods are functions defined within classes.

    # Creating a class and an object
    class Person:
        def __init__(self, name, age):
            self.name = name
            self.age = age
    
        def greet(self):
            print(f"Hello, my name is {self.name} and I am {self.age} years old.")
    
    # Creating an object of the class
    person1 = Person("Alice", 30)
    person1.greet()  # Output: Hello, my name is Alice and I am 30 years old.
                

Standard Libraries

Python has many built-in libraries that provide various functionalities. Some of the commonly used libraries include:

    # Example using the math library
    import math
    print(math.sqrt(16))  # Output: 4.0
                

UNIT-V: Data Structures, Searching, and Sorting Algorithms

1. Data Structures

Data structures are a way of organizing and storing data efficiently. Let's look at some common data structures in Python.

1.1 Arrays

Arrays are used to store multiple values in a single variable. In Python, arrays can be represented using lists, as Python does not have a dedicated array data structure.

    # Creating an array using a list
    arr = [1, 2, 3, 4, 5]
    print(arr)  # Output: [1, 2, 3, 4, 5]
                

1.2 Lists

Lists in Python are dynamic arrays that can store elements of different types and sizes. They can be modified after creation by adding, removing, or changing elements.

    # Creating a list
    lst = [10, 20, 30, 40]
    print(lst)  # Output: [10, 20, 30, 40]
                

1.3 Sets

Sets are unordered collections of unique elements. They do not allow duplicates and are useful for membership tests and mathematical operations like union and intersection.

    # Creating a set
    s = {1, 2, 3, 4}
    print(s)  # Output: {1, 2, 3, 4}
    
    # Adding and removing elements
    s.add(5)
    s.remove(2)
    print(s)  # Output: {1, 3, 4, 5}
                

1.4 Stacks

A stack is a collection of elements with two main operations: push (adding an element) and pop (removing an element). It follows the Last In, First Out (LIFO) principle.

    # Stack operations using a list
    stack = []
    stack.append(1)  # Push
    stack.append(2)  # Push
    stack.append(3)  # Push
    print(stack)  # Output: [1, 2, 3]
    
    stack.pop()  # Pop
    print(stack)  # Output: [1, 2]
                

1.5 Queues

A queue is a collection of elements that follows the First In, First Out (FIFO) principle. Elements are added at the back and removed from the front.

    # Queue operations using collections.deque
    from collections import deque
    queue = deque()
    queue.append(1)  # Enqueue
    queue.append(2)  # Enqueue
    queue.append(3)  # Enqueue
    print(queue)  # Output: deque([1, 2, 3])
    
    queue.popleft()  # Dequeue
    print(queue)  # Output: deque([2, 3])
                

2. Searching Algorithms

Searching algorithms are used to find a specific element in a data structure. Below are two common searching algorithms: Linear Search and Binary Search.

2.1 Linear Search

Linear search is a simple method that checks every element in a list until the target element is found.

    # Linear Search
    def linear_search(arr, target):
        for i in range(len(arr)):
            if arr[i] == target:
                return i  # Return the index of the target element
        return -1  # Target not found
    
    arr = [5, 3, 8, 4, 2]
    target = 4
    result = linear_search(arr, target)
    print("Element found at index:", result)  # Output: Element found at index: 3
                

2.2 Binary Search

Binary search works on sorted arrays. It repeatedly divides the search interval in half. If the target value is less than the middle element, the search continues on the left half, otherwise, it searches the right half.

    # Binary Search
    def binary_search(arr, target):
        low = 0
        high = len(arr) - 1
        while low <= high:
            mid = (low + high) // 2
            if arr[mid] == target:
                return mid  # Target found
            elif arr[mid] < target:
                low = mid + 1  # Search right half
            else:
                high = mid - 1  # Search left half
        return -1  # Target not found
    
    arr = [1, 2, 3, 4, 5, 6, 7, 8]
    target = 4
    result = binary_search(arr, target)
    print("Element found at index:", result)  # Output: Element found at index: 3
                

3. Sorting Algorithms

Sorting algorithms are used to arrange elements in a specific order, either ascending or descending. Below are three common sorting algorithms: Bubble Sort, Selection Sort, and Insertion Sort.

3.1 Bubble Sort

Bubble sort works by repeatedly stepping through the list, comparing adjacent elements, and swapping them if they are in the wrong order. This process repeats until the list is sorted.

    # Bubble Sort
    def bubble_sort(arr):
        n = len(arr)
        for i in range(n):
            for j in range(0, n-i-1):
                if arr[j] > arr[j+1]:
                    arr[j], arr[j+1] = arr[j+1], arr[j]  # Swap
        return arr
    
    arr = [64, 34, 25, 12, 22, 11, 90]
    sorted_arr = bubble_sort(arr)
    print("Sorted array:", sorted_arr)  # Output: Sorted array: [11, 12, 22, 25, 34, 64, 90]
                

3.2 Selection Sort

Selection sort works by repeatedly finding the minimum element from the unsorted part of the list and swapping it with the first unsorted element.

    # Selection Sort
    def selection_sort(arr):
        for i in range(len(arr)):
            min_idx = i
            for j in range(i+1, len(arr)):
                if arr[j] < arr[min_idx]:
                    min_idx = j
            arr[i], arr[min_idx] = arr[min_idx], arr[i]  # Swap
        return arr
    
    arr = [64, 34, 25, 12, 22, 11, 90]
    sorted_arr = selection_sort(arr)
    print("Sorted array:", sorted_arr)  # Output: Sorted array: [11, 12, 22, 25, 34, 64, 90]
                

3.3 Insertion Sort

Insertion sort works by taking each element and inserting it into the correct position in the sorted part of the list.

    # Insertion Sort
    def insertion_sort(arr):
        for i in range(1, len(arr)):
            key = arr[i]
            j = i-1
            while j >= 0 and key < arr[j]:
                arr[j+1] = arr[j]
                j -= 1
            arr[j+1] = key
        return arr
    
    arr = [64, 34, 25, 12, 22, 11, 90]
    sorted_arr = insertion_sort(arr)
    print("Sorted array:", sorted_arr)  # Output: Sorted array: [11, 12, 22, 25, 34, 64, 90]