Skip to main content

Python Programming: Complete Guide from Basics to Advanced

By · · Updated · 27 min read

Python Programming: Complete Study Guide for Polytechnic Students

Introduction to Python

Python is one of the most popular and versatile programming languages in the world today. Created by Guido van Rossum in 1991, Python has become the go-to language for beginners and experienced developers alike. Its simple, readable syntax makes it perfect for learning programming concepts, while its powerful libraries and frameworks make it suitable for professional development.

Why Python is Essential for Polytechnic Students:

  1. Industry Demand: Python is used by major tech companies including Google, Netflix, Spotify, NASA, and Instagram
  2. Versatility: Used in web development, data science, artificial intelligence, automation, and scientific computing
  3. Easy to Learn: Readable syntax that resembles English, making it ideal for beginners
  4. Career Opportunities: High-paying jobs in software development, data analysis, machine learning, and DevOps
  5. Academic Applications: Perfect for engineering calculations, simulations, and project work

Real-World Applications of Python:

  • Web Development: Django and Flask frameworks power millions of websites
  • Data Science: Pandas, NumPy, and Matplotlib for data analysis and visualization
  • Machine Learning: TensorFlow and PyTorch for AI and neural networks
  • Automation: Scripting repetitive tasks and system administration
  • Scientific Computing: Research in physics, biology, and engineering
  • Game Development: Pygame library for 2D game creation

Chapter 1: Python Fundamentals

1.1 What Makes Python Special?

Python stands out from other programming languages due to several key characteristics:

Interpreted Language: Python code is executed line by line, making debugging easier and development faster. You don't need to compile code before running it.

Dynamically Typed: Variable types are determined at runtime, so you don't need to declare types explicitly. This makes code more flexible but requires careful attention to data types.

High-Level Abstraction: Python handles memory management, garbage collection, and low-level operations automatically, letting you focus on solving problems.

Extensive Standard Library: Python comes with built-in modules for file I/O, regular expressions, networking, databases, and more.

Cross-Platform: Python runs on Windows, macOS, Linux, and even mobile devices with minimal or no code changes.

1.2 Setting Up Python Environment

Installation Steps:

  1. Download Python: Visit python.org and download the latest version (3.11 or higher recommended)
  2. Run Installer: Check "Add Python to PATH" during installation
  3. Verify Installation: Open command prompt and type:
    python --version
  4. Install IDE: Recommended options include:
    • VS Code: Lightweight with excellent Python extensions
    • PyCharm: Full-featured IDE specifically for Python
    • Jupyter Notebook: Interactive environment for data science

Writing Your First Python Program:

# This is a comment - Python ignores lines starting with #
print("Hello, World!")
print("Welcome to Python Programming")

# Python uses indentation to define code blocks
if True:
    print("This line is indented")
    print("Indentation is crucial in Python")

Understanding the Python Interpreter:

  • Python reads code from top to bottom
  • Each statement is executed in sequence
  • Errors stop execution and display helpful messages
  • The interactive shell (REPL) lets you test code immediately

Chapter 2: Variables and Data Types

2.1 Understanding Variables

Variables are containers that store data values. In Python, you create a variable by assigning a value to a name.

Variable Naming Rules:

  • Must start with a letter or underscore (_)
  • Can contain letters, numbers, and underscores
  • Case-sensitive (Name and name are different)
  • Cannot use Python reserved keywords (if, for, while, etc.)
  • Should be descriptive (student_name is better than sn)

Best Practices for Variable Names:

# Good variable names
student_name = "Rahul"
max_marks = 100
is_passed = True

# Avoid these
x = "Rahul"  # Not descriptive
2nd_student = "Rahul"  # Starts with number
student-name = "Rahul"  # Hyphens not allowed

2.2 Python Data Types

Python has several built-in data types, each designed for specific purposes:

Numeric Types

Integers (int): Whole numbers without decimal points

age = 20
student_count = 150
negative_number = -50

# Python handles large integers automatically
big_number = 12345678901234567890
print(type(age))  # Output: <class 'int'>

Floating-Point Numbers (float): Numbers with decimal points

height = 5.9
pi = 3.14159
scientific_notation = 2.5e3  # 2500.0

# Be careful with floating-point precision
result = 0.1 + 0.2  # Results in 0.30000000000000004

Complex Numbers (complex): Numbers with real and imaginary parts

complex_num = 3 + 4j
print(complex_num.real)  # 3.0
print(complex_num.imag)  # 4.0

Text Type

Strings (str): Sequences of characters

# Creating strings
name = "Chetan Sharma"
single_quotes = 'Also valid'
multiline = """This string
spans multiple
lines"""

# String operations
greeting = "Hello"
print(len(greeting))        # 5 (length)
print(greeting[0])          # H (indexing)
print(greeting[-1])        # o (last character)
print(greeting[0:3])        # Hel (slicing)
print(greeting.upper())     # HELLO
print(greeting.lower())     # hello
print(greeting + " World")  # Hello World (concatenation)

Sequence Types

Lists: Ordered, mutable collections

# Creating lists
fruits = ["apple", "banana", "cherry"]
mixed_list = [1, "hello", 3.14, True]
nested_list = [[1, 2], [3, 4], [5, 6]]

# List operations
fruits.append("orange")      # Add item
fruits.insert(1, "mango")    # Insert at index
fruits.remove("banana")      # Remove item
last_fruit = fruits.pop()    # Remove and return last item
fruits.sort()                # Sort in place
print(len(fruits))           # Get length
print(fruits[0])             # Access by index
print(fruits[-1])            # Last item
print(fruits[0:2])           # Slice [start:end]

Tuples: Ordered, immutable collections

# Creating tuples
coordinates = (10, 20)
person = ("Rahul", 20, "Engineering")
single_item = (5,)  # Note the comma for single item

# Tuple operations (limited due to immutability)
print(coordinates[0])        # 10
print(len(person))          # 3
x, y = coordinates          # Unpacking

# Tuples are useful for fixed data
rgb_color = (255, 128, 0)
database_config = ("localhost", 3306, "username", "password")

Mapping Type

Dictionaries (dict): Key-value pairs

# Creating dictionaries
student = {
    "name": "Priya",
    "age": 21,
    "course": "Computer Science",
    "marks": [85, 90, 78, 92]
}

# Dictionary operations
print(student["name"])              # Access value
student["age"] = 22                 # Update value
student["city"] = "Delhi"           # Add new key-value
student.get("grade", "N/A")        # Safe access with default
student.keys()                       # Get all keys
student.values()                     # Get all values
student.items()                      # Get all key-value pairs

# Checking and removing
if "name" in student:
    print("Name exists")
    
removed_value = student.pop("age")  # Remove and return

Set Types

Sets: Unordered collections of unique elements

# Creating sets
unique_numbers = {1, 2, 3, 4, 5}
from_list = set([1, 2, 2, 3, 3, 3])  # {1, 2, 3}

# Set operations
unique_numbers.add(6)           # Add element
unique_numbers.remove(3)        # Remove element (error if not exists)
unique_numbers.discard(10)      # Remove if exists (no error)

# Mathematical operations
set_a = {1, 2, 3, 4}
set_b = {3, 4, 5, 6}
union = set_a | set_b           # {1, 2, 3, 4, 5, 6}
intersection = set_a & set_b    # {3, 4}
difference = set_a - set_b      # {1, 2}

Boolean Type

Booleans (bool): True or False values

is_valid = True
is_empty = False

# Boolean operations
result = True and False    # False
result = True or False     # True
result = not True          # False

# Comparison operators return booleans
x = 5
y = 10
print(x < y)      # True
print(x == y)     # False
print(x != y)     # True

2.3 Type Conversion

Python allows converting between data types:

# Converting to string
str_number = str(42)          # "42"
str_float = str(3.14)         # "3.14"

# Converting to integer
int_from_string = int("100")  # 100
int_from_float = int(3.9)     # 3 (truncates decimal)

# Converting to float
float_from_string = float("3.14")  # 3.14
float_from_int = float(42)         # 42.0

# Converting to list
list_from_string = list("hello")   # ['h', 'e', 'l', 'l', 'o']
list_from_tuple = list((1, 2, 3)) # [1, 2, 3]

# Converting to tuple
tuple_from_list = tuple([1, 2, 3]) # (1, 2, 3)

# Converting to set (removes duplicates)
set_from_list = set([1, 2, 2, 3, 3, 3])  # {1, 2, 3}

Chapter 3: Operators and Expressions

3.1 Arithmetic Operators

a = 15
b = 4

# Basic arithmetic
print(a + b)     # 19 (Addition)
print(a - b)     # 11 (Subtraction)
print(a * b)     # 60 (Multiplication)
print(a / b)     # 3.75 (Division - always returns float)
print(a // b)    # 3 (Floor division - integer result)
print(a % b)     # 3 (Modulo - remainder)
print(a ** b)    # 50625 (Exponentiation - 15^4)

# Practical examples
total_students = 150
batch_size = 30
batches_needed = total_students // batch_size  # 5
remaining = total_students % batch_size        # 0

# Compound assignment operators
x = 10
x += 5      # x = x + 5 (now 15)
x -= 3      # x = x - 3 (now 12)
x *= 2      # x = x * 2 (now 24)
x /= 4      # x = x / 4 (now 6.0)

3.2 Comparison Operators

x = 10
y = 20

# Comparison operators return True or False
print(x == y)     # False (Equal to)
print(x != y)     # True (Not equal to)
print(x < y)      # True (Less than)
print(x > y)      # False (Greater than)
print(x <= y)     # True (Less than or equal)
print(x >= y)     # False (Greater than or equal)

# Comparing strings (lexicographical order)
print("apple" < "banana")   # True
print("Hello" == "hello")   # False (case-sensitive)

3.3 Logical Operators

# Logical operators combine boolean expressions
age = 25
has_id = True

# and - both conditions must be True
if age >= 18 and has_id:
    print("Allowed to enter")

# or - at least one condition must be True
is_student = True
is_senior = False
if is_student or is_senior:
    print("Eligible for discount")

# not - reverses the boolean value
is_raining = False
if not is_raining:
    print("You can go outside")

# Truth tables
print(True and True)    # True
print(True and False)   # False
print(True or False)    # True
print(False or False)   # False
print(not True)         # False

3.4 Membership and Identity Operators

# in - checks if value exists in sequence
fruits = ["apple", "banana", "cherry"]
print("apple" in fruits)      # True
print("grape" in fruits)      # False

# not in - checks if value doesn't exist
print("grape" not in fruits)  # True

# is - checks if two variables reference same object
list1 = [1, 2, 3]
list2 = [1, 2, 3]
list3 = list1

print(list1 is list2)     # False (different objects)
print(list1 is list3)     # True (same object)
print(list1 == list2)     # True (same values)

# is not - opposite of is
print(list1 is not list2) # True

Chapter 4: Control Flow Statements

4.1 Conditional Statements (if-elif-else)

Conditional statements allow your program to make decisions based on conditions.

# Basic if statement
age = 20
if age >= 18:
    print("You are an adult")
    print("You can vote")

# if-else statement
marks = 65
if marks >= 40:
    print("Congratulations! You passed")
else:
    print("Sorry, you failed. Better luck next time")

# if-elif-else chain (multiple conditions)
percentage = 85

if percentage >= 90:
    grade = "A+"
elif percentage >= 80:
    grade = "A"
elif percentage >= 70:
    grade = "B"
elif percentage >= 60:
    grade = "C"
elif percentage >= 50:
    grade = "D"
else:
    grade = "F"

print(f"Your grade is: {grade}")

# Nested if statements
is_student = True
age = 20

if is_student:
    if age < 18:
        print("Minor student")
    else:
        print("Adult student")
else:
    print("Not a student")

# Ternary operator (shorthand for simple if-else)
age = 20
status = "Adult" if age >= 18 else "Minor"
print(status)  # Adult

4.2 Loop Statements

Loops allow you to execute code repeatedly.

For Loops

# Iterating over a list
fruits = ["apple", "banana", "cherry"]
for fruit in fruits:
    print(f"I like {fruit}")

# Using range() function
# range(start, stop, step)
for i in range(5):          # 0, 1, 2, 3, 4
    print(i)

for i in range(1, 6):       # 1, 2, 3, 4, 5
    print(i)

for i in range(0, 10, 2):   # 0, 2, 4, 6, 8 (even numbers)
    print(i)

# Iterating over string
for char in "Python":
    print(char)

# Iterating over dictionary
student = {"name": "Rahul", "age": 20, "course": "CS"}
for key in student:
    print(f"{key}: {student[key]}")

for key, value in student.items():
    print(f"{key}: {value}")

# Enumerate for index and value
fruits = ["apple", "banana", "cherry"]
for index, fruit in enumerate(fruits):
    print(f"{index}: {fruit}")

# Zip for multiple sequences
names = ["Alice", "Bob", "Charlie"]
ages = [25, 30, 35]
for name, age in zip(names, ages):
    print(f"{name} is {age} years old")

While Loops

# Basic while loop
count = 0
while count < 5:
    print(f"Count: {count}")
    count += 1

# User input validation
password = ""
while len(password) < 8:
    password = input("Enter password (min 8 chars): ")
    if len(password) < 8:
        print("Password too short!")

print("Password accepted")

# Infinite loop with break
while True:
    user_input = input("Enter 'quit' to exit: ")
    if user_input.lower() == "quit":
        break
    print(f"You entered: {user_input}")

4.3 Loop Control Statements

# break - exits the loop immediately
for i in range(10):
    if i == 5:
        break
    print(i)  # Prints 0, 1, 2, 3, 4

# continue - skips current iteration
for i in range(10):
    if i % 2 == 0:  # If even
        continue
    print(i)  # Prints only odd numbers: 1, 3, 5, 7, 9

# pass - does nothing (placeholder)
for i in range(5):
    if i == 2:
        pass  # TODO: handle this case later
    print(i)

# else clause with loops (executes when loop completes normally)
for i in range(5):
    print(i)
else:
    print("Loop completed successfully")

# else doesn't execute if break is used
for i in range(5):
    if i == 3:
        break
    print(i)
else:
    print("This won't print because of break")

4.4 Practical Loop Examples

# Calculate factorial
n = 5
factorial = 1
for i in range(1, n + 1):
    factorial *= i
print(f"{n}! = {factorial}")  # 120

# Print multiplication table
number = 7
for i in range(1, 11):
    print(f"{number} x {i} = {number * i}")

# Find prime numbers
for num in range(2, 50):
    is_prime = True
    for i in range(2, int(num ** 0.5) + 1):
        if num % i == 0:
            is_prime = False
            break
    if is_prime:
        print(f"{num} is prime")

# Pattern printing
rows = 5
for i in range(1, rows + 1):
    print("*" * i)
# Output:
# *
# **
# ***
# ****
# *****

Chapter 5: Functions in Python

5.1 Defining and Calling Functions

Functions are reusable blocks of code that perform specific tasks.

# Basic function definition
def greet():
    print("Hello, World!")

# Calling the function
greet()  # Output: Hello, World!

# Function with parameters
def greet_person(name):
    print(f"Hello, {name}!")

greet_person("Rahul")  # Output: Hello, Rahul!

# Function with multiple parameters
def add_numbers(a, b):
    result = a + b
    return result

sum_result = add_numbers(5, 3)
print(sum_result)  # Output: 8

# Function with default parameters
def power(base, exponent=2):
    return base ** exponent

print(power(3))      # 9 (3^2)
print(power(2, 3))   # 8 (2^3)

# Function with return statement
def calculate_area(length, width):
    area = length * width
    return area

result = calculate_area(10, 5)
print(f"Area: {result}")  # Area: 50

# Function returning multiple values
def get_min_max(numbers):
    return min(numbers), max(numbers)

minimum, maximum = get_min_max([3, 1, 4, 1, 5, 9])
print(f"Min: {minimum}, Max: {maximum}")  # Min: 1, Max: 9

5.2 Types of Function Arguments

# Positional arguments (order matters)
def describe_person(name, age, city):
    print(f"{name} is {age} years old and lives in {city}")

describe_person("Alice", 25, "Delhi")

# Keyword arguments (order doesn't matter)
describe_person(age=30, city="Mumbai", name="Bob")

# Mixing positional and keyword arguments
describe_person("Charlie", city="Bangalore", age=35)

# Arbitrary arguments (*args)
def sum_all(*numbers):
    return sum(numbers)

print(sum_all(1, 2, 3))      # 6
print(sum_all(1, 2, 3, 4, 5)) # 15

# Arbitrary keyword arguments (**kwargs)
def print_info(**kwargs):
    for key, value in kwargs.items():
        print(f"{key}: {value}")

print_info(name="Alice", age=25, city="Delhi")

# Combining all argument types
def complex_function(a, b, *args, default="value", **kwargs):
    print(f"a: {a}, b: {b}")
    print(f"args: {args}")
    print(f"default: {default}")
    print(f"kwargs: {kwargs}")

complex_function(1, 2, 3, 4, 5, default="custom", x=10, y=20)

5.3 Lambda Functions

Lambda functions are small, anonymous functions defined with the lambda keyword.

# Basic lambda function
square = lambda x: x ** 2
print(square(5))  # 25

# Lambda with multiple arguments
add = lambda x, y: x + y
print(add(3, 4))  # 7

# Using lambda with map()
numbers = [1, 2, 3, 4, 5]
squared = list(map(lambda x: x ** 2, numbers))
print(squared)  # [1, 4, 9, 16, 25]

# Using lambda with filter()
evens = list(filter(lambda x: x % 2 == 0, numbers))
print(evens)  # [2, 4]

# Using lambda with sorted()
students = [("Alice", 85), ("Bob", 92), ("Charlie", 78)]
sorted_by_grade = sorted(students, key=lambda x: x[1], reverse=True)
print(sorted_by_grade)  # [('Bob', 92), ('Alice', 85), ('Charlie', 78)]

5.4 Built-in Functions

Python provides many useful built-in functions:

# Mathematical functions
numbers = [3, 1, 4, 1, 5, 9, 2, 6]
print(len(numbers))        # 8 (length)
print(sum(numbers))        # 31 (sum)
print(max(numbers))        # 9 (maximum)
print(min(numbers))        # 1 (minimum)
print(abs(-10))            # 10 (absolute value)
print(round(3.14159, 2))   # 3.14 (round to 2 decimal places)
print(pow(2, 3))           # 8 (power)
print(divmod(17, 5))       # (3, 2) (quotient and remainder)

# Type conversion
print(int("42"))           # 42
print(float("3.14"))       # 3.14
print(str(42))             # "42"
print(list("hello"))       # ['h', 'e', 'l', 'l', 'o']
print(tuple([1, 2, 3]))    # (1, 2, 3)
print(set([1, 2, 2, 3]))   # {1, 2, 3}

# Input/Output
name = input("Enter your name: ")  # Get user input
print(f"Hello, {name}!")

# Type checking
print(type(42))            # <class 'int'>
print(isinstance(42, int)) # True

# Range and enumeration
print(list(range(5)))      # [0, 1, 2, 3, 4]
print(list(enumerate(["a", "b", "c"])))  # [(0, 'a'), (1, 'b'), (2, 'c')]

# Zip
list1 = [1, 2, 3]
list2 = ['a', 'b', 'c']
print(list(zip(list1, list2)))  # [(1, 'a'), (2, 'b'), (3, 'c')]

# All and any
print(all([True, True, False]))  # False
print(any([True, True, False]))  # True

# Map and filter
numbers = [1, 2, 3, 4, 5]
doubled = list(map(lambda x: x * 2, numbers))
evens = list(filter(lambda x: x % 2 == 0, numbers))

Chapter 6: Object-Oriented Programming (OOP)

6.1 Classes and Objects

Object-oriented programming allows you to model real-world entities as objects with properties (attributes) and behaviors (methods).

# Defining a class
class Student:
    # Class attribute (shared by all instances)
    school = "Polytechnic College"
    
    # Constructor method (called when object is created)
    def __init__(self, name, age, course):
        # Instance attributes (unique to each object)
        self.name = name
        self.age = age
        self.course = course
        self.marks = []
    
    # Instance method
    def add_mark(self, mark):
        self.marks.append(mark)
    
    def get_average(self):
        if len(self.marks) == 0:
            return 0
        return sum(self.marks) / len(self.marks)
    
    def display_info(self):
        print(f"Name: {self.name}")
        print(f"Age: {self.age}")
        print(f"Course: {self.course}")
        print(f"School: {self.school}")
        print(f"Average: {self.get_average():.2f}")

# Creating objects (instances)
student1 = Student("Rahul", 20, "Computer Science")
student2 = Student("Priya", 21, "Electronics")

# Using object methods
student1.add_mark(85)
student1.add_mark(90)
student1.add_mark(78)

student1.display_info()

6.2 Inheritance

Inheritance allows a class to inherit attributes and methods from another class.

# Base class (Parent)
class Person:
    def __init__(self, name, age):
        self.name = name
        self.age = age
    
    def introduce(self):
        print(f"Hi, I'm {self.name} and I'm {self.age} years old")

# Derived class (Child)
class Teacher(Person):
    def __init__(self, name, age, subject, experience):
        # Call parent class constructor
        super().__init__(name, age)
        self.subject = subject
        self.experience = experience
    
    def introduce(self):
        # Override parent method
        super().introduce()
        print(f"I teach {self.subject} with {self.experience} years of experience")
    
    def teach(self):
        print(f"{self.name} is teaching {self.subject}")

class Student(Person):
    def __init__(self, name, age, course, roll_number):
        super().__init__(name, age)
        self.course = course
        self.roll_number = roll_number
    
    def study(self):
        print(f"{self.name} is studying {self.course}")

# Using inherited classes
teacher = Teacher("Mr. Sharma", 35, "Mathematics", 10)
student = Student("Alice", 20, "Computer Science", "CS2023001")

teacher.introduce()
teacher.teach()

student.introduce()
student.study()

6.3 Encapsulation and Access Modifiers

class BankAccount:
    def __init__(self, account_number, owner, balance=0):
        self.account_number = account_number  # Public
        self.owner = owner                    # Public
        self._balance = balance               # Protected (convention)
        self.__pin = "1234"                   # Private (name mangling)
    
    # Getter method
    def get_balance(self):
        return self._balance
    
    # Setter method with validation
    def deposit(self, amount):
        if amount > 0:
            self._balance += amount
            print(f"Deposited {amount}. New balance: {self._balance}")
        else:
            print("Invalid deposit amount")
    
    def withdraw(self, amount):
        if 0 < amount <= self._balance:
            self._balance -= amount
            print(f"Withdrew {amount}. New balance: {self._balance}")
        else:
            print("Insufficient funds or invalid amount")
    
    def verify_pin(self, pin):
        return pin == self.__pin

# Using encapsulation
account = BankAccount("1234567890", "Rahul", 1000)

# Accessing public attributes
print(account.account_number)
print(account.owner)

# Accessing protected attribute (not recommended, but possible)
print(account._balance)

# Accessing private attribute (will raise error or return mangled name)
# print(account.__pin)  # AttributeError
# print(account._BankAccount__pin)  # Possible but not recommended

# Using getter and setter methods
print(account.get_balance())
account.deposit(500)
account.withdraw(200)

6.4 Polymorphism

Polymorphism allows objects of different classes to be treated as objects of a common base class.

class Shape:
    def area(self):
        pass
    
    def perimeter(self):
        pass

class Rectangle(Shape):
    def __init__(self, width, height):
        self.width = width
        self.height = height
    
    def area(self):
        return self.width * self.height
    
    def perimeter(self):
        return 2 * (self.width + self.height)

class Circle(Shape):
    def __init__(self, radius):
        self.radius = radius
    
    def area(self):
        import math
        return math.pi * self.radius ** 2
    
    def perimeter(self):
        import math
        return 2 * math.pi * self.radius

class Triangle(Shape):
    def __init__(self, a, b, c):
        self.a = a
        self.b = b
        self.c = c
    
    def area(self):
        # Using Heron's formula
        s = (self.a + self.b + self.c) / 2
        import math
        return math.sqrt(s * (s - self.a) * (s - self.b) * (s - self.c))
    
    def perimeter(self):
        return self.a + self.b + self.c

# Polymorphism in action
shapes = [
    Rectangle(5, 3),
    Circle(4),
    Triangle(3, 4, 5)
]

for shape in shapes:
    print(f"Shape: {type(shape).__name__}")
    print(f"Area: {shape.area():.2f}")
    print(f"Perimeter: {shape.perimeter():.2f}")
    print()

Chapter 7: File Handling and Exception Handling

7.1 Working with Files

# Writing to a file
with open("example.txt", "w") as file:
    file.write("Hello, World!\n")
    file.write("This is a new line.\n")

# Reading from a file
with open("example.txt", "r") as file:
    content = file.read()
    print(content)

# Reading line by line
with open("example.txt", "r") as file:
    for line in file:
        print(line.strip())  # strip() removes newline characters

# Appending to a file
with open("example.txt", "a") as file:
    file.write("This line is appended.\n")

# Reading all lines into a list
with open("example.txt", "r") as file:
    lines = file.readlines()
    print(lines)

# Working with CSV files
import csv

# Writing CSV
with open("students.csv", "w", newline="") as file:
    writer = csv.writer(file)
    writer.writerow(["Name", "Age", "Course"])
    writer.writerow(["Rahul", 20, "CS"])
    writer.writerow(["Priya", 21, "EC"])

# Reading CSV
with open("students.csv", "r") as file:
    reader = csv.reader(file)
    for row in reader:
        print(row)

# Working with JSON
import json

# Writing JSON
data = {
    "name": "Rahul",
    "age": 20,
    "courses": ["Python", "Java", "DBMS"],
    "marks": {"Python": 85, "Java": 90}
}

with open("student.json", "w") as file:
    json.dump(data, file, indent=4)

# Reading JSON
with open("student.json", "r") as file:
    loaded_data = json.load(file)
    print(loaded_data)

7.2 Exception Handling

# Basic try-except
try:
    result = 10 / 0
except ZeroDivisionError:
    print("Cannot divide by zero!")

# Handling multiple exceptions
try:
    number = int(input("Enter a number: "))
    result = 100 / number
    print(f"Result: {result}")
except ValueError:
    print("Invalid input! Please enter a valid number.")
except ZeroDivisionError:
    print("Cannot divide by zero!")
except Exception as e:
    print(f"An unexpected error occurred: {e}")

# try-except-else-finally
try:
    file = open("data.txt", "r")
    content = file.read()
except FileNotFoundError:
    print("File not found!")
else:
    print("File read successfully!")
    print(content)
finally:
    print("This always executes")
    try:
        file.close()
    except:
        pass

# Raising exceptions
def validate_age(age):
    if age < 0:
        raise ValueError("Age cannot be negative")
    if age > 150:
        raise ValueError("Age seems unrealistic")
    return True

try:
    validate_age(-5)
except ValueError as e:
    print(f"Validation error: {e}")

# Custom exceptions
class InsufficientBalanceError(Exception):
    def __init__(self, balance, amount):
        self.balance = balance
        self.amount = amount
        self.message = f"Insufficient balance: {balance}. Required: {amount}"
        super().__init__(self.message)

class BankAccount:
    def __init__(self, balance=0):
        self.balance = balance
    
    def withdraw(self, amount):
        if amount > self.balance:
            raise InsufficientBalanceError(self.balance, amount)
        self.balance -= amount
        return self.balance

# Using custom exception
account = BankAccount(100)
try:
    account.withdraw(200)
except InsufficientBalanceError as e:
    print(e)

Chapter 8: Advanced Python Concepts

8.1 List Comprehensions

# Basic list comprehension
numbers = [1, 2, 3, 4, 5]
squares = [x**2 for x in numbers]
print(squares)  # [1, 4, 9, 16, 25]

# List comprehension with condition
evens = [x for x in numbers if x % 2 == 0]
print(evens)  # [2, 4]

# Nested list comprehension
matrix = [[i*j for j in range(1, 4)] for i in range(1, 4)]
print(matrix)  # [[1, 2, 3], [2, 4, 6], [3, 6, 9]]

# Dictionary comprehension
squares_dict = {x: x**2 for x in range(1, 6)}
print(squares_dict)  # {1: 1, 2: 4, 3: 9, 4: 16, 5: 25}

# Set comprehension
squares_set = {x**2 for x in range(10)}
print(squares_set)  # {0, 1, 4, 9, 16, 25, 36, 49, 64, 81}

# Generator expression (memory efficient)
sum_of_squares = sum(x**2 for x in range(1000000))
print(sum_of_squares)

8.2 Decorators

import time
import functools

# Basic decorator
def my_decorator(func):
    def wrapper(*args, **kwargs):
        print("Before function call")
        result = func(*args, **kwargs)
        print("After function call")
        return result
    return wrapper

@my_decorator
def say_hello():
    print("Hello!")

say_hello()

# Timing decorator
def timer(func):
    @functools.wraps(func)
    def wrapper(*args, **kwargs):
        start = time.time()
        result = func(*args, **kwargs)
        end = time.time()
        print(f"{func.__name__} took {end - start:.4f} seconds")
        return result
    return wrapper

@timer
def slow_function():
    time.sleep(1)
    return "Done"

slow_function()

# Decorator with arguments
def repeat(times):
    def decorator(func):
        def wrapper(*args, **kwargs):
            for _ in range(times):
                result = func(*args, **kwargs)
            return result
        return wrapper
    return decorator

@repeat(times=3)
def greet():
    print("Hello!")

greet()

8.3 Generators

# Generator function
def count_up_to(n):
    count = 1
    while count <= n:
        yield count
        count += 1

# Using generator
for number in count_up_to(5):
    print(number)  # 1, 2, 3, 4, 5

# Generator expression
squares_gen = (x**2 for x in range(1000000))

# Memory efficient - processes one item at a time
print(next(squares_gen))  # 0
print(next(squares_gen))  # 1

# Infinite generator
def fibonacci():
    a, b = 0, 1
    while True:
        yield a
        a, b = b, a + b

# Get first 10 Fibonacci numbers
fib = fibonacci()
for _ in range(10):
    print(next(fib))

# Practical example: Reading large files
def read_large_file(file_path):
    with open(file_path, "r") as file:
        for line in file:
            yield line.strip()

# Process file line by line without loading entire file into memory
# for line in read_large_file("huge_file.txt"):
#     process_line(line)

8.4 Context Managers

# Using context manager with 'with' statement
with open("file.txt", "r") as file:
    content = file.read()
# File is automatically closed

# Creating custom context manager
class DatabaseConnection:
    def __init__(self, connection_string):
        self.connection_string = connection_string
        self.connection = None
    
    def __enter__(self):
        print(f"Connecting to {self.connection_string}")
        self.connection = f"Connection to {self.connection_string}"
        return self.connection
    
    def __exit__(self, exc_type, exc_val, exc_tb):
        print("Closing connection")
        self.connection = None
        return False  # Don't suppress exceptions

# Using custom context manager
with DatabaseConnection("localhost:5432") as conn:
    print(f"Using {conn}")

# Context manager using decorator
from contextlib import contextmanager

@contextmanager
def managed_resource(name):
    print(f"Acquiring {name}")
    resource = f"Resource-{name}"
    try:
        yield resource
    finally:
        print(f"Releasing {name}")

# Using decorator-based context manager
with managed_resource("Database") as resource:
    print(f"Using {resource}")

Chapter 9: Python for Data Science

9.1 NumPy Basics

import numpy as np

# Creating arrays
arr1 = np.array([1, 2, 3, 4, 5])
arr2 = np.array([[1, 2, 3], [4, 5, 6], [7, 8, 9]])

# Array properties
print(arr2.shape)    # (3, 3)
print(arr2.ndim)     # 2
print(arr2.size)     # 9
print(arr2.dtype)    # int64

# Special arrays
zeros = np.zeros((3, 3))
ones = np.ones((2, 4))
identity = np.eye(3)
random_arr = np.random.rand(3, 3)
range_arr = np.arange(0, 10, 2)  # [0, 2, 4, 6, 8]
linspace_arr = np.linspace(0, 1, 5)  # 5 evenly spaced values

# Array operations
arr = np.array([1, 2, 3, 4, 5])
print(arr + 2)       # [3, 4, 5, 6, 7]
print(arr * 2)       # [2, 4, 6, 8, 10]
print(arr ** 2)      # [1, 4, 9, 16, 25]
print(np.sqrt(arr))  # [1., 1.414, 1.732, 2., 2.236]

# Statistical operations
print(np.mean(arr))  # 3.0
print(np.median(arr)) # 3.0
print(np.std(arr))   # 1.414
print(np.sum(arr))   # 15
print(np.min(arr))   # 1
print(np.max(arr))   # 5

# Indexing and slicing
arr = np.array([[1, 2, 3], [4, 5, 6], [7, 8, 9]])
print(arr[0, 1])     # 2
print(arr[1, :])     # [4, 5, 6]
print(arr[:, 1])     # [2, 5, 8]
print(arr[0:2, 0:2]) # [[1, 2], [4, 5]]

# Boolean indexing
arr = np.array([1, 2, 3, 4, 5, 6, 7, 8, 9, 10])
evens = arr[arr % 2 == 0]
print(evens)  # [2, 4, 6, 8, 10]

9.2 Pandas Basics

import pandas as pd

# Creating Series
s = pd.Series([1, 3, 5, np.nan, 6, 8])
print(s)

# Creating DataFrame
df = pd.DataFrame({
    'Name': ['Rahul', 'Priya', 'Amit', 'Sneha'],
    'Age': [20, 21, 22, 20],
    'Course': ['CS', 'EC', 'ME', 'CS'],
    'Marks': [85, 92, 78, 88]
})

print(df)

# Basic operations
print(df.head())        # First 5 rows
print(df.tail())        # Last 5 rows
print(df.info())        # DataFrame info
print(df.describe())    # Statistical summary
print(df.shape)         # Dimensions
print(df.columns)       # Column names

# Selecting data
print(df['Name'])       # Single column
print(df[['Name', 'Age']])  # Multiple columns
print(df[df['Age'] > 20])   # Filter rows
print(df.loc[0])        # Row by index
print(df.loc[0, 'Name'])  # Specific value

# Sorting
print(df.sort_values('Marks', ascending=False))

# Grouping
print(df.groupby('Course')['Marks'].mean())

# Adding columns
df['Grade'] = df['Marks'].apply(lambda x: 'A' if x >= 90 else 'B' if x >= 80 else 'C')
print(df)

# Handling missing data
df_with_nan = pd.DataFrame({
    'A': [1, 2, np.nan],
    'B': [4, np.nan, 6]
})
print(df_with_nan.dropna())      # Drop rows with NaN
print(df_with_nan.fillna(0))     # Fill NaN with 0

# Reading and writing files
# df = pd.read_csv('data.csv')
# df.to_csv('output.csv', index=False)
# df = pd.read_excel('data.xlsx')

9.3 Data Visualization with Matplotlib

import matplotlib.pyplot as plt

# Line plot
x = [1, 2, 3, 4, 5]
y = [2, 4, 6, 8, 10]

plt.figure(figsize=(8, 6))
plt.plot(x, y, marker='o', linestyle='-', color='blue', label='y = 2x')
plt.title('Simple Line Plot')
plt.xlabel('X-axis')
plt.ylabel('Y-axis')
plt.legend()
plt.grid(True)
plt.show()

# Bar chart
categories = ['A', 'B', 'C', 'D']
values = [23, 45, 56, 78]

plt.figure(figsize=(8, 6))
plt.bar(categories, values, color=['red', 'green', 'blue', 'orange'])
plt.title('Bar Chart Example')
plt.xlabel('Categories')
plt.ylabel('Values')
plt.show()

# Scatter plot
x = np.random.rand(50)
y = np.random.rand(50)
colors = np.random.rand(50)
sizes = 1000 * np.random.rand(50)

plt.figure(figsize=(8, 6))
plt.scatter(x, y, c=colors, s=sizes, alpha=0.5)
plt.title('Scatter Plot')
plt.xlabel('X')
plt.ylabel('Y')
plt.show()

# Pie chart
sizes = [30, 25, 25, 20]
labels = ['Python', 'Java', 'C++', 'JavaScript']
colors = ['gold', 'yellowgreen', 'lightcoral', 'lightskyblue']

plt.figure(figsize=(8, 6))
plt.pie(sizes, labels=labels, colors=colors, autopct='%1.1f%%', startangle=90)
plt.title('Programming Language Popularity')
plt.axis('equal')
plt.show()

# Subplots
fig, axes = plt.subplots(2, 2, figsize=(12, 10))

axes[0, 0].plot([1, 2, 3], [1, 4, 9])
axes[0, 0].set_title('Plot 1')

axes[0, 1].bar(['A', 'B'], [3, 4])
axes[0, 1].set_title('Plot 2')

axes[1, 0].scatter([1, 2, 3], [1, 4, 9])
axes[1, 0].set_title('Plot 3')

axes[1, 1].pie([1, 2, 3], labels=['X', 'Y', 'Z'])
axes[1, 1].set_title('Plot 4')

plt.tight_layout()
plt.show()

Chapter 10: Practical Python Projects

10.1 Student Management System

import json
from datetime import datetime

class StudentManagementSystem:
    def __init__(self, data_file="students.json"):
        self.data_file = data_file
        self.students = self.load_data()
    
    def load_data(self):
        try:
            with open(self.data_file, "r") as file:
                return json.load(file)
        except FileNotFoundError:
            return {}
    
    def save_data(self):
        with open(self.data_file, "w") as file:
            json.dump(self.students, file, indent=4)
    
    def add_student(self, roll_number, name, course, age):
        if roll_number in self.students:
            print(f"Student with roll number {roll_number} already exists!")
            return False
        
        self.students[roll_number] = {
            "name": name,
            "course": course,
            "age": age,
            "marks": {},
            "attendance": [],
            "joined_date": datetime.now().strftime("%Y-%m-%d")
        }
        self.save_data()
        print(f"Student {name} added successfully!")
        return True
    
    def add_marks(self, roll_number, subject, marks):
        if roll_number not in self.students:
            print("Student not found!")
            return False
        
        self.students[roll_number]["marks"][subject] = marks
        self.save_data()
        print(f"Marks added for {subject}")
        return True
    
    def get_student_report(self, roll_number):
        if roll_number not in self.students:
            print("Student not found!")
            return None
        
        student = self.students[roll_number]
        marks = student["marks"]
        
        if marks:
            average = sum(marks.values()) / len(marks)
        else:
            average = 0
        
        report = f"""
        Student Report
        ==============
        Name: {student['name']}
        Roll Number: {roll_number}
        Course: {student['course']}
        Age: {student['age']}
        Joined: {student['joined_date']}
        
        Marks:
        """
        for subject, mark in marks.items():
            report += f"  {subject}: {mark}\n"
        
        report += f"\nAverage: {average:.2f}"
        return report
    
    def list_all_students(self):
        if not self.students:
            print("No students in the system.")
            return
        
        print("\nAll Students:")
        print("-" * 50)
        for roll_number, student in self.students.items():
            print(f"{roll_number}: {student['name']} ({student['course']})")

# Example usage
# sms = StudentManagementSystem()
# sms.add_student("CS001", "Rahul Kumar", "Computer Science", 20)
# sms.add_marks("CS001", "Python", 85)
# sms.add_marks("CS001", "Mathematics", 90)
# print(sms.get_student_report("CS001"))

10.2 Calculator with Error Handling

class Calculator:
    def __init__(self):
        self.history = []
    
    def add(self, a, b):
        result = a + b
        self._log_operation(f"{a} + {b} = {result}")
        return result
    
    def subtract(self, a, b):
        result = a - b
        self._log_operation(f"{a} - {b} = {result}")
        return result
    
    def multiply(self, a, b):
        result = a * b
        self._log_operation(f"{a} * {b} = {result}")
        return result
    
    def divide(self, a, b):
        try:
            if b == 0:
                raise ValueError("Cannot divide by zero")
            result = a / b
            self._log_operation(f"{a} / {b} = {result}")
            return result
        except ValueError as e:
            print(f"Error: {e}")
            return None
    
    def power(self, a, b):
        result = a ** b
        self._log_operation(f"{a} ^ {b} = {result}")
        return result
    
    def square_root(self, a):
        try:
            if a < 0:
                raise ValueError("Cannot calculate square root of negative number")
            result = a ** 0.5
            self._log_operation(f"√{a} = {result}")
            return result
        except ValueError as e:
            print(f"Error: {e}")
            return None
    
    def _log_operation(self, operation):
        self.history.append(operation)
    
    def show_history(self):
        if not self.history:
            print("No operations performed yet.")
            return
        
        print("\nCalculation History:")
        print("-" * 30)
        for i, operation in enumerate(self.history, 1):
            print(f"{i}. {operation}")
    
    def clear_history(self):
        self.history.clear()
        print("History cleared.")

# Interactive calculator
def run_calculator():
    calc = Calculator()
    
    while True:
        print("\n=== Python Calculator ===")
        print("1. Add")
        print("2. Subtract")
        print("3. Multiply")
        print("4. Divide")
        print("5. Power")
        print("6. Square Root")
        print("7. Show History")
        print("8. Clear History")
        print("9. Exit")
        
        choice = input("\nEnter your choice (1-9): ")
        
        if choice == "9":
            print("Thank you for using Python Calculator!")
            break
        
        elif choice == "7":
            calc.show_history()
        
        elif choice == "8":
            calc.clear_history()
        
        elif choice in ["1", "2", "3", "4", "5"]:
            try:
                a = float(input("Enter first number: "))
                b = float(input("Enter second number: "))
                
                if choice == "1":
                    result = calc.add(a, b)
                elif choice == "2":
                    result = calc.subtract(a, b)
                elif choice == "3":
                    result = calc.multiply(a, b)
                elif choice == "4":
                    result = calc.divide(a, b)
                elif choice == "5":
                    result = calc.power(a, b)
                
                print(f"Result: {result}")
            except ValueError:
                print("Invalid input! Please enter valid numbers.")
        
        elif choice == "6":
            try:
                a = float(input("Enter number: "))
                result = calc.square_root(a)
                if result is not None:
                    print(f"Result: {result}")
            except ValueError:
                print("Invalid input! Please enter a valid number.")
        
        else:
            print("Invalid choice! Please try again.")

# Uncomment to run
# run_calculator()

10.3 File Organizer Script

import os
import shutil
from pathlib import Path

def organize_files(directory):
    """
    Organizes files in the given directory by their extensions.
    Creates folders for different file types and moves files accordingly.
    """
    # Define file categories
    file_types = {
        'Images': ['.jpg', '.jpeg', '.png', '.gif', '.bmp', '.svg', '.webp'],
        'Documents': ['.pdf', '.doc', '.docx', '.txt', '.rtf', '.odt'],
        'Spreadsheets': ['.xls', '.xlsx', '.csv', '.ods'],
        'Presentations': ['.ppt', '.pptx', '.odp'],
        'Videos': ['.mp4', '.avi', '.mkv', '.mov', '.wmv', '.flv'],
        'Audio': ['.mp3', '.wav', '.flac', '.aac', '.ogg', '.wma'],
        'Archives': ['.zip', '.rar', '.7z', '.tar', '.gz'],
        'Code': ['.py', '.js', '.html', '.css', '.java', '.cpp', '.c', '.h'],
        'Executables': ['.exe', '.msi', '.dmg', '.pkg', '.deb', '.rpm']
    }
    
    # Create category folders
    for category in file_types.keys():
        category_path = Path(directory) / category
        category_path.mkdir(exist_ok=True)
    
    # Create 'Others' folder for uncategorized files
    others_path = Path(directory) / 'Others'
    others_path.mkdir(exist_ok=True)
    
    # Track statistics
    moved_files = {category: 0 for category in file_types.keys()}
    moved_files['Others'] = 0
    
    # Process each file in the directory
    for file_path in Path(directory).iterdir():
        if file_path.is_file():
            file_extension = file_path.suffix.lower()
            
            # Find appropriate category
            moved = False
            for category, extensions in file_types.items():
                if file_extension in extensions:
                    destination = Path(directory) / category / file_path.name
                    
                    # Handle duplicate filenames
                    counter = 1
                    while destination.exists():
                        stem = file_path.stem
                        suffix = file_path.suffix
                        destination = Path(directory) / category / f"{stem}_{counter}{suffix}"
                        counter += 1
                    
                    shutil.move(str(file_path), str(destination))
                    moved_files[category] += 1
                    moved = True
                    break
            
            # If no category matched, move to Others
            if not moved:
                destination = others_path / file_path.name
                counter = 1
                while destination.exists():
                    stem = file_path.stem
                    suffix = file_path.suffix
                    destination = others_path / f"{stem}_{counter}{suffix}"
                    counter += 1
                
                shutil.move(str(file_path), str(destination))
                moved_files['Others'] += 1
    
    # Print summary
    print("\nFile Organization Complete!")
    print("=" * 40)
    total_moved = 0
    for category, count in moved_files.items():
        if count > 0:
            print(f"{category}: {count} files")
            total_moved += count
    print("=" * 40)
    print(f"Total files organized: {total_moved}")

# Example usage
# organize_files("/path/to/your/directory")

Chapter 11: Best Practices and Tips

11.1 Python Coding Standards (PEP 8)

# Naming conventions
student_name = "Rahul"      # Variables: lowercase with underscores
MAX_SIZE = 100              # Constants: uppercase with underscores
class StudentRecord:        # Classes: CapWords (CamelCase)
    def calculate_average(self):  # Methods: lowercase with underscores
        pass

# Indentation (4 spaces)
def example_function():
    if True:
        print("Proper indentation")  # 4 spaces
        if True:
            print("Nested block")      # 8 spaces

# Line length (max 79 characters)
# Use parentheses for implicit line continuation
result = (first_variable + second_variable + 
          third_variable + fourth_variable)

# Whitespace
# Good
result = x + y
# Bad
result=x+y

# Comments
# Use complete sentences, capitalize first letter
# Leave one space after #
def complex_function():  # This explains the function purpose
    pass

# Docstrings
def calculate_area(length, width):
    """
    Calculate the area of a rectangle.
    
    Args:
        length (float): The length of the rectangle
        width (float): The width of the rectangle
    
    Returns:
        float: The calculated area
    """
    return length * width

11.2 Common Mistakes to Avoid

# Mistake 1: Modifying list while iterating
numbers = [1, 2, 3, 4, 5]
# Wrong
for num in numbers:
    if num % 2 == 0:
        numbers.remove(num)  # Don't do this!

# Correct
numbers = [num for num in numbers if num % 2 != 0]

# Mistake 2: Using mutable default arguments
def add_item(item, item_list=[]):  # Wrong!
    item_list.append(item)
    return item_list

# Correct
def add_item(item, item_list=None):
    if item_list is None:
        item_list = []
    item_list.append(item)
    return item_list

# Mistake 3: Not closing files
# Wrong
file = open("data.txt", "r")
data = file.read()
# File might not close if error occurs

# Correct
with open("data.txt", "r") as file:
    data = file.read()
# File automatically closed

# Mistake 4: Using 'is' for equality comparison
# Wrong
if x is 5:  # Checks identity, not equality
    pass

# Correct
if x == 5:  # Checks equality
    pass

# Mistake 5: Not handling exceptions
# Wrong
data = int(input("Enter number: "))
result = 10 / data

# Correct
try:
    data = int(input("Enter number: "))
    result = 10 / data
except ValueError:
    print("Invalid input")
except ZeroDivisionError:
    print("Cannot divide by zero")

11.3 Python Learning Path

Beginner Level (Weeks 1-4):

  • ✅ Basic syntax and data types
  • ✅ Variables and operators
  • ✅ Control flow (if, loops)
  • ✅ Functions
  • ✅ Basic file handling
  • ✅ Simple projects (calculator, todo list)

Intermediate Level (Weeks 5-8):

  • ✅ Object-oriented programming
  • ✅ Exception handling
  • ✅ Modules and packages
  • ✅ List comprehensions
  • ✅ Lambda functions
  • ✅ Working with APIs
  • ✅ Database operations (SQLite)

Advanced Level (Weeks 9-12):

  • ✅ Decorators and generators
  • ✅ Context managers
  • ✅ Multithreading/Multiprocessing
  • ✅ Regular expressions
  • ✅ Web frameworks (Flask/Django)
  • ✅ Data science libraries (NumPy, Pandas)
  • ✅ Testing and debugging

Expert Level (Ongoing):

  • ✅ Design patterns
  • ✅ Performance optimization
  • ✅ C extensions
  • ✅ Machine learning (scikit-learn, TensorFlow)
  • ✅ Cloud deployment
  • ✅ Open source contribution

Summary and Key Takeaways

Congratulations on completing this comprehensive Python programming guide! Here's what you've learned:

Core Concepts Mastered:

  1. Python Fundamentals: Syntax, variables, data types, and operators
  2. Control Flow: Conditional statements and loops for program control
  3. Functions: Creating reusable code blocks with parameters and return values
  4. Data Structures: Lists, tuples, dictionaries, and sets for data organization
  5. Object-Oriented Programming: Classes, objects, inheritance, and polymorphism
  6. File Handling: Reading, writing, and managing files
  7. Error Handling: Writing robust code with exception handling
  8. Advanced Concepts: List comprehensions, decorators, generators, and context managers

Practical Skills Acquired:

  • Building complete applications (Student Management System, Calculator)
  • Data analysis with NumPy and Pandas
  • Data visualization with Matplotlib
  • File organization and automation scripts
  • Best practices for writing clean, maintainable code

Next Steps for Mastery:

  1. Practice Daily: Write small programs every day to reinforce concepts
  2. Build Projects: Create real-world applications to apply your knowledge
  3. Read Code: Study open-source Python projects on GitHub
  4. Join Communities: Participate in Python forums and local meetups
  5. Contribute: Start contributing to open-source projects
  6. Specialize: Choose a domain (web dev, data science, AI) and dive deeper

Resources for Continued Learning:

  • Official Documentation: docs.python.org
  • Practice Platforms: LeetCode, HackerRank, Codewars
  • YouTube Channels: Corey Schafer, Tech With Tim, Sentdex
  • Books: "Python Crash Course" by Eric Matthes, "Fluent Python" by Luciano Ramalho
  • Communities: r/learnpython, Python Discord, Stack Overflow

Download Additional Study Materials

For comprehensive PDF notes, assignments, and practice exercises, download the following resources:

📥 Python Assignment 1 - Basics and Data Types

📥 Python Assignment 2 - Control Flow and Functions

📥 Python Unit 3 - Functions and Modules

📥 Python Unit 4 - Object-Oriented Programming

📥 Python Unit 5 - File Handling and Exception Handling


This comprehensive Python guide is designed specifically for polytechnic and diploma students. The content is regularly updated to align with current HSBTE syllabus requirements and industry best practices.

Last Updated: February 19, 2026
Author: Chetan Sharma
Version: 2.0

For questions, clarifications, or suggestions, feel free to reach out through the contact page.

Happy Coding! 🐍✨