L
LLLOS.ai
Learn
L

Chapter 1 — Review Of Python Basics

Class 12 · Computer Science

Overview

Chapter 1 — Review Of Python Basics Master Diagram

Introduction: This chapter revisits the fundamental concepts of Python that form the foundation for Class 12 Computer Science. It consolidates students' understanding of syntax, core data types, control flow, functions and basic data structures through short programs and examples. Importance: A strong grasp of these basics is essential for writing correct, readable programs, for solving algorithmic problems in examinations, and for progressing to advanced topics such as file handling, object‑oriented programming and data processing. Key themes: identifiers and keywords, variables and data types (int, float, complex, bool, str), type conversion and casting, operators and precedence, expressions, conditional statements (if, if‑else, nested if), loops (for, while, break, continue, else with loops), strings and common string operations (indexing, slicing, methods), sequence operations (lists, tuples) and basic collection types (sets, dictionaries), functions (definition, parameters, return, scope, default/keyword/variable arguments), simple modularity (importing modules), basic input/output and file operations, error detection and simple debugging. What the student will learn:…

Learning Objectives

  • Define basic Python data types (int, float, bool, str) and give examples
  • Explain the use of arithmetic, relational, logical and assignment operators with example expressions
  • Differentiate between mutable and immutable data types (list vs tuple) and state implications for program behavior
  • Write Python programs using control structures (if-elif-else, for, while) to solve typical exam problems
  • Implement and invoke user-defined functions with parameters, return values, and demonstrate variable scope
  • Trace and dry-run Python code to determine variable values, program flow and final output
  • Apply list, tuple, dictionary and set operations (indexing, slicing, insertion, deletion, lookup) in programs
  • Use string manipulation methods and formatted input/output to process and present text data

Topics in this chapter

20 topics · tap a topic title to jump straight to it.

🧾1

Python Basics & Syntax

💻 COMPUTER SCIENCE / IT

Python Basics & Syntax

Key Point: Slicing: sequence[start:stop:step] → elements from index start up to stop-1, with step increment. Omitting start/stop uses defaults (start=0, stop=len).

Overview: Python is a high-level, interpreted, general-purpose language. Its syntax emphasizes readability (use of indentation) and minimal punctuation. Core concepts include variables, data types, operators, statements, control flow, functions, collections (list/tuple/dict/set), I/O, and modules.

Key points:

  • Identifiers & Keywords: Identifiers are names given to variables, functions, etc. Keywords (like if, for, def) are reserved.
  • Indentation: Blocks are defined by indentation (usually 4 spaces). No braces. Correct indentation is syntactically required.
  • Statements & Expressions: A statement performs an action (assignment, loop), an expression evaluates to a value.
  • Comments: Single-line with #, docstrings with triple quotes for multi-line comments or documentation.
  • Data types: Numeric (int, float), bool, str, list, tuple, dict, set. Types are dynamic and inferred at runtime.
  • Input/Output: input() reads strings, print() writes output. Convert types using int(), float(), str().
  • Operators: Arithmetic (+, -, *, /, //, %), comparison (==, !=, <, >=), logical (and, or, not), membership (in), identity (is).
  • Control flow: if/elif/else, loops (for, while), break, continue, pass.
  • Functions: Declared with def name(params):, may return values with return. Parameters can have default values, and Python supports keyword and positional arguments.
  • Collections: Lists are mutable ordered collections; tuples are ordered immutable; dictionaries store key:value pairs; sets are unordered unique elements.
  • String handling: Strings are sequences supporting indexing, slicing (s[start:stop:step]), concatenation, methods like .split(), .join(), .format() or f-strings.
  • Exception handling: Use try/except/finally to handle runtime errors gracefully.
  • Modules & Packages: Reuse code with import module or from module import name. Standard library offers many utilities.

Good practices: meaningful variable names, consistent indentation, use comments and docstrings, avoid global variables, prefer list/dict comprehensions for concise code, handle exceptions where appropriate.

Short inline code examples: x = int(input()) converts input to integer. for i in range(5): print(i) loops 0..4. def add(a,b): return a+b.

📌 Examples
  • ATM PIN check (decision): pin = input('Enter PIN: ') if pin == '1234': print('Access granted') else: print('Access denied')
  • Temperature conversion (real-life formula): # Celsius to Fahrenheit c = float(input('Celsius: ')) f = (c * 9/5) + 32 print('Fahrenheit:', f)
  • Billing calculator (using lists and sum): prices = [49.99, 10.0, 5.5] total = sum(prices) discount = 0.1 if total > 50 else 0 final = total * (1 - discount) print('Total:', final)
  • Attendance mark (loop + condition): students = ['A', 'B', 'C'] present = ['A','C'] for s in students: status = 'Present' if s in present else 'Absent' print(s, status)
  • Find maximum in a list (iteration): def find_max(nums): if not nums: return None m = nums[0] for x in nums[1:]: if x > m: m = x return m print(find_max([3,7,2,9]))
  • File I/O (logging attendance): with open('attendance.txt','a') as f: f.write('StudentA, Present\n')
🧮 Formulas
  1. \[Slicing: sequence[start:stop:step] → elements from index start up to stop-1\]
    \[with step increment\]
    \[Omitting start/stop uses defaults (start=0\]
    \[stop=len).\]
  2. \[range behavior: range(start\]
    \[stop\]
    \[step) generates integers start..stop-1 stepping by step. range(n) is 0..n-1.\]
  3. \[Operator precedence (high → low): () → ** → unary +,- → *,/,//,% → +,- → <<,>> → & → ^ → | → comparisons → not → and → or.\]
  4. \[Function syntax: def func_name(parameters):\n '''docstring'''\n statements\n return value\]
  5. \[Common conversions: int(x)\]
    \[float(x)\]
    \[str(x)\]
    \[list(iterable)\]
    \[tuple(iterable)\]
    \[dict(pairs)\]
    \[set(iterable)\]
  6. \[List comprehension template: [expr for item in iterable if condition] — concise way to build lists\]
📊2

Data Types and Type Conversion

💻 COMPUTER SCIENCE / IT

Data Types and Type Conversion

Key Point: int(x): truncates toward zero (int(3.7) → 3; int(-2.9) → -2)

What are data types?
Data types classify values that a program manipulates. Python is dynamically typed: every value has a type and variables refer to values (no explicit declaration required). Common built-in types:

  • Numeric: int (integers), float (floating-point), complex (a + bj)
  • Sequence: str (strings), list (mutable ordered), tuple (immutable ordered)
  • Mapping: dict (key → value)
  • Set: set (unordered unique elements)
  • Boolean: bool (True, False) — note: bool is a subclass of int (True == 1)
  • NoneType: None (no value)

Type conversion (casting)
Conversion between types can be implicit or explicit:

  • Implicit conversion (coercion): Python automatically converts types in certain operations. Example: int + float → float (3 + 2.5 → 5.5).
  • Explicit conversion (casting): Use built-in constructors to convert values: int(), float(), str(), bool(), list(), tuple(), set(), dict(), complex().

Important rules & behaviors:

  • int(x) converts a float by truncating toward zero: int(3.7) → 3, int(-2.9) → -2.
  • float(int) preserves integrality but becomes floating: float(5) → 5.0.
  • complex(a, b) builds complex numbers: complex(2, 3) → 2+3j.
  • str(x) returns printable representation of x; converting a non-numeric string to int/float raises ValueError: int('12') → 12, int('12.3') raises error.
  • bool(x) is False for zero, 0.0, empty sequences/collections ("", [], (), {}), and None; otherwise True.
  • Sequence conversions: list(tuple), tuple(list), set(list). Converting list of key-value pairs to dict: dict([('a',1),('b',2)]) → {'a':1,'b':2}.

Examples in code

age_str = '18'
age = int(age_str)            # explicit: '18' -> 18
price = 19.95
items = 3
total = price * items       # implicit: float * int -> float (59.85)
flag = bool([])             # False, because empty list is falsy
pair_list = [('x', 1), ('y', 2)]
coords = tuple([1, 2, 3])   # convert list to tuple

When to convert? Convert when you need a specific type for an operation: parse user input (strings) to numbers for arithmetic; freeze a list into a tuple when immutability is required; convert to str for printing or concatenation.

📌 Examples
  • User input: age = int(input('Enter age: ')) # converts numeric string to int for comparisons and math
  • Price calculation: total = float(price_str) * int(quantity_str) # convert strings from a form to numeric values
  • Empty check with bool: if not items: # items == [] or '' or 0 will be False
  • Immutable copy: ids_tuple = tuple(ids_list) # convert a list to a tuple to protect from changes
  • Build dict: marks = dict([('Alice', 90), ('Bob', 85)]) # convert list of pairs into a mapping
🧮 Formulas
  1. \[int(x): truncates toward zero (int(3.7) → 3\]
    \[int(-2.9) → -2)\]
  2. \[float(x): converts numeric types to floating-point (float(3) → 3.0)\]
  3. \[complex(a\]
    \[b): a + b*j (complex(2, 3) → 2+3j)\]
  4. \[int + float → float (e.g., 3 + 2.5 → 5.5)\]
  5. \[bool(x) is False for: 0, 0.0, '', []\]
    \[(), {}\]
    \[set()\]
    \[None\]
    \[otherwise True\]
  6. \[dict(pairs): build mapping from sequence of (key\]
    \[value) pairs\]
💻3

Variables and Memory

💻 COMPUTER SCIENCE / IT

Variables and Memory

Key Point: Variable name regex: ^[A-Za-z_][A-Za-z0-9_]*$ (must not be a reserved keyword).

What is a variable?
A variable is a name (identifier) that refers to a value (object) stored in memory. In Python variables are labels bound to objects — Python uses dynamic typing so a name can be rebound to objects of different types during program execution.

Variable naming and rules
Valid names follow the pattern: ^[A-Za-z_][A-Za-z0-9_]*$. Names cannot be Python keywords (like if, for, None). Use meaningful names, avoid starting with digits, and follow conventions (lower_case_with_underscores for variables, ALL_CAPS for constants).

Python memory model (simple)
- Objects live on the heap. Variables are entries in a namespace (like a table) that hold references (pointers) to those objects.
- id(obj) gives a unique integer for the object’s identity during its lifetime (implementation detail). sys.getsizeof(obj) returns the memory footprint of the object itself (not including referenced objects).

Assignment and references
When you do x = 10, Python creates an integer object 10 (if not present) and makes the name x refer to it. If you then do y = x, both x and y refer to the same object (aliasing). For immutable objects (int, str, tuple) changing a variable binds it to a new object; for mutable objects (list, dict, set), operations may modify the same object visible via all aliases.

Mutability and aliasing (why it matters)
Example: a = [1,2]; b = a; b.append(3) — both a and b now show [1,2,3] because they refer to the same list object. To avoid unintended sharing, use copies: shallow copy (e.g. list(), copy.copy()) or deep copy (copy.deepcopy()) for nested structures.

Lifetime and garbage collection
Objects exist as long as there are references to them. When reference count drops to zero and no other references remain, the object becomes collectible. The Python garbage collector also detects and collects many cyclic references.

Practical implications for programs
- Use descriptive names and follow naming rules.
- Be aware of mutability: return copies when exposing internal lists/dicts if you want to protect them.
- Use id() and sys.getsizeof() to inspect identity and size during debugging or optimization.
- Understand that assignment does not copy objects — it creates new references to existing objects.

Short code examples (try in Python REPL):

# binding names to objects
x = 100
y = x            # y refers to same integer object as x
print(id(x), id(y))  # same id

# mutability and aliasing
a = [1,2]
b = a
b.append(3)
print(a)          # [1, 2, 3]

# shallow vs deep copy
import copy
orig = [[1], [2]]
sh = copy.copy(orig)       # shallow: lists created, inner lists shared
dp = copy.deepcopy(orig)   # deep: whole structure copied
orig[0].append(99)
print(sh)   # shows change in inner list
print(dp)   # unaffected

# inspect size and id
import sys
s = 'hello'
print(id(s), sys.getsizeof(s))
📌 Examples
  • Example 1 — Simple assignment and rebind: x = 5; x = 'hello' — the name x first referred to integer 5, then to string 'hello'.
  • Example 2 — Aliasing with lists: a = [1,2]; b = a; b.append(3) => a is [1,2,3]. Both names point to same list object.
  • Example 3 — Prevent alias side-effects: use copy: import copy; b = copy.deepcopy(a) to make an independent copy of nested structures.
  • Example 4 — Swapping without temp: a, b = b, a — Python packs and unpacks tuples to swap references.
  • Example 5 — Inspecting identity and size: import sys; id(obj) returns an object identity integer; sys.getsizeof(obj) returns memory used by the object itself.
🧮 Formulas
  1. \[Variable name regex: ^[A-Za-z_][A-Za-z0-9_]*$ (must not be a reserved keyword).\]
  2. \[Assignment semantics: x = y => name 'x' points to the same object as name 'y' (no automatic copy).\]
  3. \[Identity check: id(obj) returns an integer identifying the object during its lifetime\]
    \[equality vs identity: (a == b) checks value equality\]
    \[(a is b) checks identity.\]
  4. \[Memory size (approx): total_size_of_structure = getsizeof(container) + sum(getsizeof(each referenced object)) — note: getsizeof does not recurse into referenced objects automatically.\]
  5. \[Swap: a\]
    \[b = b\]
    \[a (multiple assignment uses tuple packing/unpacking).\]
💻4

Operators and Expressions

💻 COMPUTER SCIENCE / IT

Operators and Expressions

Key Point: a = b * (a // b) + (a % b) (integer division & modulo identity, b>0)

Overview: An expression is a combination of operands (variables, literals) and operators that Python evaluates to produce a value. An operator is a symbol that tells Python to perform specific computations. Understanding operators, their types, precedence and associativity is essential for writing correct programs.

Operator categories:

  • Arithmetic: + (add), - (subtract), * (multiply), / (true division), // (floor division), % (modulo), ** (exponentiation). Example: a + b * c.
  • Relational / Comparison: ==, !=, <, <=, >, >=. Evaluate to Boolean values.
  • Logical: and, or, not. Combine Boolean expressions. They short-circuit (stop evaluation early) where applicable.
  • Bitwise: &, |, ^, ~, <<, >>. Operate on integer binary representations.
  • Assignment: = and augmented forms like +=, -=, *=, /=, //=, %=, **=. They assign values to variables.
  • Membership: in, not in. Test membership in sequences/collections.
  • Identity: is, is not. Test whether two references point to the same object (not just equal values).

Expression evaluation rules:

  • Precedence: Operators have an order; higher-precedence operators are evaluated before lower-precedence ones (e.g., * before +).
  • Associativity: If operators share precedence, associativity (left-to-right or right-to-left) determines evaluation order. Example: exponentiation (**) is right-to-left: 2 ** 3 ** 2 is 2 ** (3 ** 2).
  • Parentheses: Use parentheses to force a desired evaluation order.
  • Short-circuiting: For and and or, evaluation may stop early: in A and B, if A is False, B is not evaluated; in A or B, if A is True, B is not evaluated.

Operator behavior and common notes:

  • Type-sensitive: + concatenates strings or adds numbers. Mixing types often raises errors (e.g., 'str' + int).
  • Augmented assignment: x += y updates x in place when possible (mutates for lists, creates new object for immutables).
  • Bit shifts: x << n multiplies x by 2**n (for integers), x >> n divides by powers of two with sign behavior for negatives).
  • Modulo identity: For integers a, b (>0), a = b * (a // b) + (a % b).

Examples in code:

# arithmetic
bill = 1200
gst = bill * 0.18
total = bill + gst  # + has lower precedence than *

# logical / membership
age = 20
can_vote = age >= 18 and 'citizen' in status_list

# augmented assignment
balance -= withdrawal  # same as balance = balance - withdrawal

# bitwise (permissions)
perm = 0b110  # read+write
perm |= 0b001  # add execute permission

# short-circuit
def expensive_check():
    ...
ok = fast_check() and expensive_check()  # expensive_check only runs if fast_check() is True

Common pitfalls:

  • Confusing == (equality) with is (identity).
  • Relying on floating-point equality due to precision errors; use a tolerance for comparisons.
  • Assuming left-to-right for all operators; exponentiation is right-to-left.
📌 Examples
  • Calculate final bill with discount: total = price * qty; discount_amount = total * (discount_pct / 100); payable = total - discount_amount
  • Age and eligibility check: is_eligible = (age >= 18) and (age <= 60) and (citizen == 'yes')
  • Toggling file permissions (bitwise): perm = perm ^ 0b100 flips the read bit
  • Concatenating strings and repeating: s = 'Hi' + ' there' ; triple = 'ha' * 3 # 'hahaha'
  • Using augmented assignment in a loop: sum = 0; for x in nums: sum += x # faster to write and clear intention
  • Membership test: if student_name in class_list: print('present')
🧮 Formulas
  1. \[a = b * (a // b) + (a % b) (integer division & modulo identity\]
    \[b>0)\]
  2. \[a % b = a - b * floor(a / b)\]
  3. \[x += y is equivalent to x = x + y (with in-place mutation for mutable types when possible)\]
  4. \[x << n = x * 2**n (left shift multiplies by powers of two for integers)\]
  5. \[x >> n ≈ floor(x / 2**n) (right shift divides by powers of two\]
    \[sign depends on implementation for negatives)\]
  6. \[Operator precedence (high to low\]
    \[common subset): ** -> unary + - -> *, /, //, % -> +, - -> <<, >> -> &, ^, | -> comparisons -> not -> and -> or\]
⚖️5

Loops and Iteration

💻 COMPUTER SCIENCE / IT

Loops and Iteration

Key Point: Sum of first n natural numbers (can be computed by loop or formula): S = n(n + 1) / 2

What are loops? Loops (iteration) are control structures that repeat a block of code until a condition is met. They let you perform repetitive tasks without writing the same code many times.

Types in Python

  • for loop: Iterates over an iterable (list, tuple, string, range, etc.). Use when the number of iterations or the collection is known.
  • while loop: Repeats as long as a condition is true. Use when repetition depends on a condition that changes inside the loop.

Basic syntax

# for loop
for item in iterable:
    # body

# while loop
while condition:
    # body

Iteration protocol: Any object that implements __iter__ (returns an iterator) and whose iterator implements __next__ can be used with for. Generators produce iterators lazily.

Control statements inside loops

  • break: Exit the nearest loop immediately.
  • continue: Skip the rest of current iteration and continue with next.
  • pass: No-op placeholder.
  • else with a loop: Runs when the loop completes without encountering a break.

Common patterns

  • Counting / summation (accumulator pattern).
  • Searching (stop early with break).
  • Filtering or transforming collections (often with list comprehensions).
  • Nested loops for 2D data (matrices, pattern printing).
  • Loops with step control: range(start, stop, step).

Careful with infinite loops: A while True or mis-specified condition can run forever unless you use break or update the condition correctly.

When to use iteration over recursion: Iteration usually uses less call-stack space and is preferred for simple repeated tasks; recursion is useful for divide-and-conquer and problems naturally defined recursively.

Example short snippets

# sum of numbers in a list
total = 0
for x in [1,2,3,4]:
    total += x

# while loop example: repeat until input valid
n = -1
while n < 0:
    n = int(input('Enter non-negative integer: '))

# generator iteration
def squares(n):
    for i in range(n):
        yield i*i
for s in squares(5):
    print(s)

Performance note: Each pass through a loop has cost; time complexity often expressed using Big-O. A single loop over n items is O(n); nested loops over n twice is typically O(n^2). Some loops that reduce the problem by a constant factor (e.g., halving) are O(log n).

📌 Examples
  • 1) Sum of first n natural numbers (for loop): n = 10 s = 0 for i in range(1, n+1): s += i print(s) # 55
  • 2) Factorial using while loop: n = 5 fact = 1 i = 1 while i <= n: fact *= i i += 1 print(fact) # 120
  • 3) Search with early exit (break): arr = [4, 7, 2, 9] key = 7 found = False for x in arr: if x == key: found = True break print('Found' if found else 'Not found')
  • 4) Nested loops — pattern printing (3 rows): for r in range(1, 4): for c in range(r): print('*', end='') print() # Output: # * # ** # ***
  • 5) Iterative Fibonacci (efficient, O(n) time, O(1) space): n = 7 a, b = 0, 1 for _ in range(n): a, b = b, a + b print(a) # 13
🧮 Formulas
  1. \[Sum of first n natural numbers (can be computed by loop or formula): S = n(n + 1) / 2\]
  2. \[Number of iterations for range(start\]
    \[stop\]
    \[step) with positive step: iterations = max(0\]
    \[ceil((stop - start)/step)) (often use len(range(start\]
    \[stop\]
    \[step)))\]
  3. \[Iterations for a loop that halves a positive integer n each time: approx. floor(log2(n)) + 1 → O(log n)\]
  4. \[Nested loops with both running n times: total steps ≈ n * n = n^2 → O(n^2)\]
  5. \[Time complexity rules: single loop over n → O(n)\]
    \[nested two loops → O(n^2)\]
    \[loop with halving → O(log n)\]
💻6

Functions

📐 MATHEMATICAL FORMULA / THEOREM

Functions

Key Point: Mathematical mapping: f: X → Y means function f maps each x in X to some y in Y.

What is a function? A function is a named block of code that performs a specific task, may accept inputs (parameters) and may return a value. In Python a function bundles logic so it can be reused, tested and understood independently.

Mathematical view: A function f maps inputs from a domain X to outputs in a codomain Y, written f: X → Y. In programming, a Python function implements such a mapping.

Basic syntax

def function_name(param1, param2=default_value):
    """Optional docstring describing the function"""
    # body
    return result  # optional
  • Return value: use return to send a result back. Without an explicit return a function returns None.
  • Docstring: first string in a function gives documentation and is available via help().

Types of parameters

  • Positional: regular parameters filled by position.
  • Default: def f(x, y=0): gives y a default value.
  • Keyword: call with names: f(x=1, y=2).
  • Variable-length: *args for extra positional args, **kwargs for extra keyword args.

Scope and lifetime

  • Local scope: variables defined inside a function are local to it.
  • Global scope: variables defined outside are global. Use global sparingly to modify globals.
  • Nonlocal: used inside nested functions to modify outer (but non-global) variables.

Kinds of functions

  • Built-in: e.g., print(), len(), sum().
  • User-defined: created with def.
  • Anonymous / lambda: short single-expression functions: lambda x: x*x.
  • Higher-order: functions that take other functions as arguments or return functions (e.g., map, filter, sorted with key).

Recursion is when a function calls itself. Useful for problems defined by smaller subproblems (factorial, tree traversal). Ensure a base case to stop recursion.

Examples of good practices

  • Keep functions single-purpose and short.
  • Name functions and parameters clearly.
  • Prefer pure functions (no side effects) when possible to ease testing.
  • Document behavior, expected types and return values in the docstring.

Small code examples

# Simple function
def add(a, b):
    """Return sum of a and b"""
    return a + b

# Default and keyword arguments
def greet(name, msg='Hello'):
    return f"{msg}, {name}!"

# Variable arguments
def join_all(*items, sep=' '):
    return sep.join(items)

# Recursion (factorial)
def factorial(n):
    if n <= 1:
        return 1
    return n * factorial(n-1)

# Lambda and higher-order usage
squares = list(map(lambda x: x*x, [1,2,3,4]))
📌 Examples
  • Calculator module: functions for add(x,y), subtract(x,y), multiply(x,y), divide(x,y) — each operation as a separate function.
  • ATM operations: functions for authenticate(user,pin), check_balance(account), withdraw(account,amount) — keeps banking logic modular.
  • Temperature conversion: c_to_f(c) returns (c * 9/5) + 32; f_to_c(f) returns (f - 32) * 5/9.
  • Data cleaning: clean_names(list_of_strings) — trims whitespace, fixes capitalization and removes invalid characters.
  • Recursion: factorial(n) calculates n! using the recurrence n! = n * (n-1)! with base case 0! = 1.
  • Higher-order: apply_discount(prices, discount_fn) where discount_fn is passed in to compute new prices (demonstrates passing a function).
🧮 Formulas
  1. \[Mathematical mapping: f: X → Y means function f maps each x in X to some y in Y.\]
  2. \[Function signature pattern: def name(param1\]
    \[param2=default, *args, **kwargs):\]
  3. \[Recurrence (factorial): n! = n × (n − 1)!\]
    \[with 0! = 1 (base case).\]
  4. \[Recurrence (Fibonacci): F(n) = F(n-1) + F(n-2)\]
    \[with F(0)=0\]
    \[F(1)=1.\]
  5. \[Composition of functions: (f ∘ g)(x) = f(g(x)).\]
  6. \[Common complexity notes: naive recursive Fibonacci ≈ O(2^n)\]
    \[iterative or memoized Fibonacci ≈ O(n).\]
💻7

Recursion

💻 COMPUTER SCIENCE / IT

Recursion

Key Point: Factorial definition: n! = n × (n−1) × (n−2) × ... × 1, with 0! = 1.

What is recursion?

Recursion is a programming technique in which a function calls itself to solve a smaller instance of the same problem until it reaches a simple, directly solvable case (the base case). A recursive solution has two parts: the base case (terminates recursion) and the recursive case (reduces the problem and calls the function again).

Why use recursion? It maps naturally to problems defined in terms of smaller subproblems (example: factorial, tree/graph traversals, divide-and-conquer algorithms). Recursion can make code simpler and easier to reason about when the problem is naturally recursive.

Important points in Python:

  • Every recursive function must have a base case to avoid infinite recursion and eventual RecursionError (maximum recursion depth exceeded).
  • Python does not perform tail-call optimization, so deep recursion can hit the recursion limit (default ~1000) and use extra stack memory.
  • Recursive solutions may have higher time/space cost than iterative ones unless memoization or other optimizations are used.

Simple examples (Python):

# Factorial (n!)
def factorial(n):
    if n == 0 or n == 1:          # base case
        return 1
    else:
        return n * factorial(n - 1)  # recursive case

# Fibonacci (naive)
def fib(n):
    if n == 0:
        return 0
    if n == 1:
        return 1
    return fib(n-1) + fib(n-2)

# GCD (Euclid's algorithm)
def gcd(a, b):
    if b == 0:
        return a
    return gcd(b, a % b)

# Towers of Hanoi (print moves)
def hanoi(n, src, dst, aux):
    if n == 1:
        print(f"Move disk 1 from {src} to {dst}")
        return
    hanoi(n-1, src, aux, dst)
    print(f"Move disk {n} from {src} to {dst}")
    hanoi(n-1, aux, dst, src)

Complexity and behavior:

  • Space complexity often includes the recursion depth (call stack). For simple linear recursion (e.g., factorial), space = O(n).
  • Time complexity depends on the recurrence relation. For example, factorial: T(n)=T(n-1)+O(1) → O(n). Naive Fibonacci: T(n)=T(n-1)+T(n-2)+O(1) → exponential (~O(φ^n)).

When to prefer recursion: problems on trees, graphs, divide-and-conquer algorithms (quick sort, merge sort), combinatorial generation, backtracking (permutations, subsets, sudoku solver).

Caveats: watch base case correctness, avoid excessive recursion depth in Python, consider memoization (caching) to convert exponential recursions (like naive Fibonacci) into linear time.

📌 Examples
  • Factorial: factorial(n) returns n * factorial(n-1) with base case factorial(0)=1. Time: O(n), Space: O(n).
  • Fibonacci (naive): fib(n)=fib(n-1)+fib(n-2). Naive time: exponential (~O(φ^n)). Use memoization to get O(n).
  • GCD (Euclid): gcd(a,b) calls gcd(b,a%b) until b==0 — efficient and uses O(log min(a,b)) steps.
  • Towers of Hanoi: moves follow recursion; number of moves is 2^n - 1 (exponential).
  • Directory traversal: recursively visit subdirectories and files (natural tree recursion).
🧮 Formulas
  1. \[Factorial definition: n! = n × (n−1) × (n−2) × ... × 1\]
    \[with 0! = 1.\]
  2. \[Recurrence for linear recursion (e.g.\]
    \[factorial): T(n) = T(n−1) + O(1) ⇒ T(n) = O(n).\]
  3. \[Recurrence for naive Fibonacci: T(n) = T(n−1) + T(n−2) + O(1) ⇒ T(n) = O(φ^n) where φ ≈ 1.618.\]
  4. \[Towers of Hanoi moves: M(n) = 2 × M(n−1) + 1\]
    \[with M(1)=1 ⇒ M(n) = 2^n − 1.\]
  5. \[Divide-and-conquer (example merge sort): T(n) = 2 T(n/2) + O(n) ⇒ T(n) = O(n log n).\]
  6. \[Space usage (call stack) for depth d recursion: Space = O(d) (plus space for local variables).\]
💻8

Modules and Libraries

💻 COMPUTER SCIENCE / IT

Modules and Libraries

Key Point: Import forms (templates): - import module_name - import module_name as alias - from module_name import name1, name2 - from module_name import * # not recommended

What is a module? A module is a file containing Python definitions (functions, classes, variables) and runnable code. Any .py file is a module. Modules help split a program into logical parts and promote code reuse.

What is a library / package? A library is a collection of modules that provide related functionality (for example, data analysis, HTTP requests). A package is a directory that groups modules and subpackages and usually contains an __init__.py file.

Why use modules and libraries?

  • Reusability: write once, use many times.
  • Modularity: separate concerns; easier testing and maintenance.
  • Namespace management: avoids name clashes by module namespaces.
  • Access to a rich standard library and third-party packages (NumPy, Pandas, requests, matplotlib, etc.).

How to import

  • import module_name — use members via module_name.member.
  • import module_name as alias — shorter name: alias.member.
  • from module_name import name1, name2 — direct access to names.
  • from module_name import * — imports all public names (not recommended).

Creating and using a module (simple example)

# file: mymath.py
PI = 3.14159

def area_circle(r):
    return PI * r * r

if __name__ == '__main__':
    # runs when executed directly, not when imported
    print('Test area:', area_circle(2))

# file: use_mymath.py
import mymath
print(mymath.area_circle(3))

Packages

A package is a folder with Python modules and (optionally) an __init__.py. Example structure:

analytics/
  __init__.py
  stats.py
  plot.py

Standard library vs third-party

Python's standard library (installed with Python) includes modules such as math, datetime, os, sys, random. Third-party libraries (e.g., numpy, pandas, requests) are installed with tools like pip.

Key behaviors and tips

  • Importing executes the module file once and caches it in sys.modules.
  • Use if __name__ == '__main__': to keep test/demo code from running on import.
  • Avoid circular imports (two modules importing each other) — refactor or import locally inside functions if needed.
  • Use virtual environments to manage project-specific library versions.

Common useful modules (short)

  • math: math.sqrt, math.factorial, math.comb, math.ceil, math.floor
  • random: random.random, random.randint, random.choice
  • datetime: datetime.datetime.now(), date arithmetic
  • os / os.path: file and path operations
  • sys: command-line args (sys.argv), interpreter info
  • json: parse and write JSON data

Example: using a third-party library

# install: pip install requests
import requests
r = requests.get('https://api.example.com/data')
if r.status_code == 200:
    data = r.json()

Summary: Modules and libraries let you organize code into reusable pieces, access vast amounts of prebuilt functionality, and keep programs maintainable and readable. Learn common import patterns, package structure, and the distinction between standard and third-party libraries to use them effectively.

📌 Examples
  • Math computations: use the math module to compute square roots and combinations: import math; area = math.pi * r * r; ways = math.comb(n, k).
  • File handling and OS tasks: use os and os.path to join paths, list directories, and check file existence: import os; files = os.listdir('.'); path = os.path.join('data', 'file.txt').
  • Web requests and APIs: use the requests library to call web APIs and parse JSON: import requests; r = requests.get('https://api.example.com'); data = r.json().
  • Data analysis: use numpy and pandas (third-party) to load CSVs, perform vectorized computations, and summarize data: import pandas as pd; df = pd.read_csv('data.csv'); df.describe().
  • Module creation and reuse: create helper functions in a file helpers.py and import them across projects: from helpers import clean_text, tokenize.
🧮 Formulas
  1. \[Import forms (templates): - import module_name - import module_name as alias - from module_name import name1\]
    \[name2 - from module_name import * # not recommended\]
  2. \[Module main guard: if __name__ == '__main__': # code to run only when module executed directly\]
  3. \[Common function signatures (examples): - math.sqrt(x) -> float - math.factorial(n) -> int - math.comb(n\]
    \[k) -> int # number of combinations (n choose k) - random.randint(a\]
    \[b) -> int # inclusive random integer\]
  4. \[Combinatorics formulas (available via math): - nCr = n! / (r! * (n-r)!) (use math.comb(n\]
    \[r)) - nPr = n! / (n-r)! (use math.perm(n\]
    \[r) in recent Python)\]
💻9

Strings

💻 COMPUTER SCIENCE / IT

Strings

Key Point: Length: n = len(s)

What is a string?
The term string refers to a sequence of characters (letters, digits, symbols, whitespace). In Python a string is an ordered, immutable sequence object used to store and manipulate text.

Key properties

  • Indexed: Each character has an integer index: 0..n-1 (positive) and -n..-1 (negative).
  • Sliced: Substrings can be obtained with slicing syntax.
  • Immutable: Once created the characters cannot be changed in place; operations produce new strings.
  • Iterable: You can loop over characters.

Basic operations (conceptual)

  • concatenation: combine strings with +
  • repetition: repeat with *
  • membership: test substring with in
  • indexing: access a character with s[i]
  • slicing: extract substring with s[start:end:step]

Common built-in methods (non-exhaustive): len(s), s.upper(), s.lower(), s.strip(), s.split(sep), sep.join(list), s.replace(old,new), s.find(sub), s.count(sub), s.startswith(pref), s.endswith(suf), format() and f-strings for templating.

Immutability example: Trying s[0] = 'X' raises an error; use slicing or concatenation to build a new string.

Escape sequences & raw strings: use \n, \t, \\ for special characters. Raw strings r"..." treat backslashes literally (useful for file paths, regular expressions).

Typical use-cases / real-life role

  • Storing names, addresses, messages (e.g., user input on forms).
  • Parsing and formatting data (CSV, logs, reports).
  • Searching and validating (email patterns, passwords).
  • Generating user-readable output (invoices, messages) using formatting.

Good practices

  • Use join to concatenate many pieces efficiently.
  • Prefer string methods over manual loops for clarity and speed.
  • When manipulating many characters often, consider using lists for in-place edits then "".join().
📌 Examples
  • 1) Indexing & slicing: name = "Anjali"; name[0] -> 'A'; name[-1] -> 'i'; name[1:4] -> 'nja'.
  • 2) Concatenation & repetition: a = "Hi "; b = "Ravi"; a + b -> 'Hi Ravi'; ('ha')*3 -> 'hahaha'.
  • 3) Formatting: invoice = f"Item: {item}, Price: {price:.2f}" -> uses f-string to format numbers.
  • 4) Splitting & joining: sentence = 'CBSE,Python,Strings'; parts = sentence.split(',') -> ['CBSE','Python','Strings']; '-'.join(parts) -> 'CBSE-Python-Strings'.
  • 5) Searching & replacing: text = 'Hello world'; text.find('world') -> 6; text.replace('world','CBSE') -> 'Hello CBSE'.
  • 6) Real-life: Validate simple email pattern: email = 'student@example.com'; if '@' in email and email.endswith('.com'): valid = True
🧮 Formulas
  1. \[Length: n = len(s)\]
  2. \[Indexing: character_at_i = s[i] (0 ≤ i < n)\]
    \[negative index s[-k] == s[n-k]\]
  3. \[Slicing: substring = s[start:end:step] — includes start\]
    \[excludes end\]
    \[defaults: start=0\]
    \[end=n\]
    \[step=1\]
  4. \[Concatenation: s3 = s1 + s2\]
  5. \[Repetition: s2 = s * m (m is integer ≥ 0)\]
  6. \[Membership: (sub in s) -> True/False\]
💻10

Lists

💻 COMPUTER SCIENCE / IT

Lists

Key Point: Creation: lst = [] or lst = [a, b, c]

What is a list?
A list in Python is an ordered, mutable collection that can hold heterogeneous items (numbers, strings, other lists, etc.). Lists are written with square brackets: [item1, item2, ...].

Key properties

  • Ordered: elements retain insertion order and are accessible by index.
  • Mutable: you can change elements in place (assign, insert, remove).
  • Heterogeneous: elements can be of different types.
  • Allow duplicates.

Creation
Empty list: lst = [] or lst = list(). With items: lst = [1, 'a', 3.14].

Indexing and slicing
Indexing: lst[0] is first element; negative indexing: lst[-1] last element. Slicing: lst[start:stop:step] returns a new list from index start up to (but not including) stop. Examples:

lst = [10,20,30,40,50]
lst[1]     # 20
lst[-2:]   # [40,50]
lst[::2]   # [10,30,50]

Common operations

  • Concatenation: a + b
  • Repetition: lst * 3
  • Membership: item in lst
  • Length: len(lst)

Important list methods

lst.append(x)     # add x at end
lst.extend(iter)   # add all items from iterable
lst.insert(i, x)   # insert x at index i
lst.remove(x)      # remove first occurrence of x
lst.pop(i=-1)      # remove and return item at i (default last)
lst.clear()        # remove all items
lst.index(x)       # return first index of x
lst.count(x)       # count occurrences
lst.sort()         # sort in-place
lst.reverse()      # reverse order in-place
new = sorted(lst)  # return a sorted copy
copy = lst.copy()  # shallow copy

List comprehensions
Concise way to create lists:

evens = [x for x in range(1,11) if x%2==0]  # [2,4,6,8,10]
squares = [x*x for x in nums]

Nested lists (lists of lists)
Used to represent matrices, adjacency lists, etc. Access by multiple indices: matrix[i][j].

Shallow vs Deep copy
Shallow copy ( lst.copy() or list() ) copies top-level list only; inner mutable objects are shared. Use import copy; copy.deepcopy(lst) to fully clone nested lists.

Time complexity (typical)

  • Indexing (read/write): O(1)
  • Append (amortized): O(1)
  • Insert/delete at arbitrary position: O(n)
  • Search (in, index): O(n)
  • Copy, slice, sort: O(n) or O(n log n) for sort

Notes for CBSE examinations

  • Show examples of indexing, slicing, and at least one list method (append/pop/insert/remove).
  • Distinguish mutable lists from immutable tuples where needed.
  • Explain shallow vs deep copy if nested lists are used.

Short code summary

# create
students = ['Asha','Ravi','Maya']
# add
students.append('Neil')
# modify
students[1] = 'Rahul'
# slice
first_two = students[:2]
# comprehension
marks = [m for m in marks_list if m>=33]

📌 Examples
  • Shopping list: items = ['milk', 'eggs', 'bread']; items.append('butter')
  • Student marks: marks = [78, 92, 61, 85]; pass_students = [m for m in marks if m>=40]
  • To-do list with priorities: tasks = [['study', 'high'], ['sleep', 'low']]; tasks[0][0] gives 'study'
  • Matrix as nested list: matrix = [[1,2,3],[4,5,6],[7,8,9]]; element at row2 col3: matrix[1][2] -> 6
  • Attendance register: names = ['A','B','C']; present = ['A','C']; absent = [n for n in names if n not in present]
  • Graph adjacency list: adj = {0: [1,2], 1: [0,3], 2: [0], 3: [1]} (lists of neighbors)
🧮 Formulas
  1. \[Creation: lst = [] or lst = [a\]
    \[b\]
    \[c]\]
  2. \[Indexing: lst[i] retrieves element at index i (0-based)\]
    \[negative index: lst[-1] last element\]
  3. \[Slicing: lst[start:stop:step] returns elements from start to stop-1 with step\]
  4. \[Comprehension: [expr for var in iterable if condition] (e.g., [x*x for x in nums if x>0])\]
  5. \[Concatenate/Repeat: new = a + b\]
    \[repeated = lst * k\]
  6. \[Methods signatures: append(x)\]
    \[extend(iterable)\]
    \[insert(i,x)\]
    \[pop(i=-1)\]
    \[remove(x)\]
    \[sort()\]
    \[reverse()\]
    \[copy()\]
💻11

Tuples

💻 COMPUTER SCIENCE / IT

Tuples

Key Point: Creation: t = (a, b, c) or t = a, b, c

What is a tuple?
A tuple is an ordered, immutable collection of items in Python. Tuples group related values together and, once created, their elements cannot be changed (no item assignment or deletion). Tuples are written with parentheses ( ) or simply by comma-separated values.

Creation

# empty tuple
empty = ()
# tuple of integers
t = (1, 2, 3)
# parentheses optional
u = 4, 5, 6
# single-element tuple (comma is mandatory)
single = (7,)

Key properties

  • Ordered: items have a defined index starting from 0.
  • Immutable: elements cannot be changed after creation (you can create a new tuple from existing ones).
  • Heterogeneous: can hold mixed types (ints, strings, lists, other tuples).
  • Hashability: a tuple is hashable (usable as dict key) only if all its elements are hashable.

Common operations and examples

t = (10, 20, 30, 40)
len(t)           # 4
t[0]              # 10 (indexing)
t[1:3]            # (20, 30) (slicing returns a tuple)
t + (50, 60)      # (10,20,30,40,50,60) (concatenation)
t * 2             # repeats elements
20 in t           # True (membership)

# methods
t.index(30)       # index of first occurrence
t.count(20)       # number of occurrences

# packing and unpacking
pair = (x, y) = (3, 4)
x, y = pair        # tuple unpacking; useful for functions returning multiple values

Tuples vs Lists
Tuples are immutable and typically lighter/faster. Use tuples for fixed collections (constants, keys), lists for collections you will modify.

Use-cases / When to use tuples

  • Fixed records like coordinates (x, y) or RGB colors (r, g, b).
  • Return multiple values from a function (Python implicitly returns tuples).
  • Use as keys in dictionaries if contents are immutable/hashable.
  • Store constant sequences such as days of the week.

Notes & tips

  • To change a tuple, convert to list, modify, then convert back: t = tuple(list(t)).
  • Nested tuples are allowed: ((1,2), (3,4)).
  • Because tuples are immutable they are safe to use where data should not change and can be slightly faster than lists.

📌 Examples
  • GPS coordinate: location = (28.7041, 77.1025) — latitude and longitude (immutable pair).
  • RGB color: color = (255, 128, 0) — red, green, blue channels as a fixed triplet.
  • Record/row: student = ('Anita', 18, 'Physics') — name, age, stream stored as a fixed record.
  • Function returning multiple values: def stats(a,b): return (a+b, a-b) — caller can unpack: s, d = stats(10,3).
  • Dictionary key: pos_dict[(x,y)] = 'occupied' — using a tuple (x,y) as an immutable key.
  • Constants list: months = ('Jan','Feb','Mar',...) — months as a constant sequence that should not change.
🧮 Formulas
  1. \[Creation: t = (a\]
    \[b\]
    \[c) or t = a\]
    \[b\]
    \[c\]
  2. \[Single element: t = (x,) # trailing comma required\]
  3. \[Length: len(t) -> integer\]
  4. \[Indexing: t[i] (i from 0 to len(t)-1)\]
  5. \[Slicing: t[i:j] -> tuple with elements from i to j-1\]
  6. \[Concatenation: t + u -> new tuple (elements of t followed by u)\]
💻12

Dictionaries

💻 COMPUTER SCIENCE / IT

Dictionaries

Key Point: Size: number_of_pairs = len(d)

What is a dictionary?
A dictionary in Python is a mutable collection that stores key:value pairs. Each key maps to a value. Dictionaries are implemented using hash tables so lookups, inserts and deletions are fast. In current Python versions the insertion order is preserved, but the primary property is mapping from unique keys to values.

Creation and syntax
You can create dictionaries using curly braces or the dict() constructor.

# empty dictionary
d = {}
# with items
student = {'roll': 21, 'name': 'Asha', 'marks': 87}
# using constructor
config = dict(timeout=30, verbose=True)

Key rules

  • Keys must be immutable types (e.g., int, float, str, tuple containing immutables).
  • Values can be any type (including lists, other dicts).
  • Keys are unique — assigning to an existing key updates its value.

Common operations and methods

  • Access: value = d[key] (KeyError if absent) or d.get(key, default) (safe)
  • Insert/Update: d[key] = value
  • Delete: del d[key], d.pop(key), d.popitem()
  • Query: len(d), key in d
  • Views: d.keys(), d.values(), d.items()
  • Other methods: d.clear(), d.update(other), d.setdefault(key, default), d.copy()
# examples of operations
d = {'a': 1}
# insert or update
d['b'] = 2           # {'a':1, 'b':2}
# get safely
x = d.get('c', 0)    # returns 0, doesn't raise
# iterate items
for k, v in d.items():
    print(k, v)

Dictionary comprehensions
Create dictionaries concisely using a comprehension:

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

Nested dictionaries
Dictionaries can contain other dictionaries — useful for structured records.

students = {
    21: {'name': 'Asha', 'marks': 87},
    22: {'name': 'Ravi', 'marks': 91}
}

How it works (brief)
Under the hood, keys are hashed to compute an index (bucket) in a table. This is why keys must be hashable (immutable). Collisions are handled internally so typical average-time complexity for lookup/insert/delete is O(1).

When to use dictionaries
Use dictionaries when you need fast lookup by a unique key (e.g., phone number lookup by name, configuration settings, counters, adjacency lists in graphs, JSON-like structured data).

Real-life examples
Phonebook (name → phone), product inventory (product_id → quantity), student database (roll → record), HTTP headers (header-name → value), JSON objects (mapping names to values).

Tips & pitfalls

  • Mutable objects (like lists) cannot be used as keys.
  • Using d.get() avoids KeyError when key might be missing.
  • Be careful with d.update() as it overwrites existing keys.
📌 Examples
  • Phonebook example: phonebook = {'Asha': '9876543210', 'Ravi': '9123456780'} print(phonebook['Asha']) # 9876543210
  • Counting characters using a dictionary: text = 'apple' count = {} for ch in text: count[ch] = count.get(ch, 0) + 1 # count -> {'a':1,'p':2,'l':1,'e':1}
  • Nested dictionary for students: students = {21: {'name':'Asha','marks':87}, 22:{'name':'Ravi','marks':91}} print(students[22]['marks']) # 91
  • Dictionary comprehension: squares = {x: x*x for x in range(1,6)} # {1:1, 2:4, 3:9, 4:16, 5:25}
🧮 Formulas
  1. \[Size: number_of_pairs = len(d)\]
  2. \[Average time complexity (typical): lookup/insert/delete ≈ O(1)\]
  3. \[Worst-case time complexity (rare\]
    \[pathological hashing collisions): O(n)\]
  4. \['membership' test: (key in d) ≈ O(1)\]
  5. \[Dictionary comprehension general form: {key_expr: value_expr for item in iterable if condition}\]
💻13

Sets

💻 COMPUTER SCIENCE / IT

Sets

Key Point: Cardinality: |A| = len(A)

What is a set?
In Python, a set is an unordered collection of unique, hashable elements. Sets model the mathematical concept of a collection with no duplicates. They are mutable (you can add/remove elements) but each element must be immutable (numbers, strings, tuples, frozensets).

Key properties

  • Unordered — no indexing; elements have no fixed position.
  • Unique — duplicates are automatically removed.
  • Mutable container — supports add/remove operations on the set itself.
  • Elements must be hashable — e.g., int, float, str, tuple; lists and dicts are not allowed.

Creation

# literal
s = {1, 2, 3}
# from iterable
s2 = set([2, 3, 4])
# empty set
empty = set()  # {} creates an empty dict, not a set

Common methods & operators

  • add(x), remove(x), discard(x), pop(), clear()
  • union: A | B or A.union(B)
  • intersection: A & B or A.intersection(B)
  • difference: A - B or A.difference(B)
  • symmetric difference: A ^ B or A.symmetric_difference(B)
  • subset/superset: A.issubset(B) / A.issuperset(B) (also A <= B, A >= B)
  • isdisjoint(B) checks whether A and B share no elements
  • len(s) gives cardinality; membership test: x in s (average O(1) time)

Set comprehension

{x*x for x in range(6)}  # {0, 1, 4, 9, 16, 25}

Practical notes
Use frozenset when you need an immutable, hashable set (e.g., as a dict key). Typical operations (add, remove, membership) are average O(1) due to hash-table implementation.

Example use-cases
Removing duplicates from data, fast membership tests (whitelists/blacklists), computing overlaps between groups (intersection), or combining categories (union).

📌 Examples
  • Remove duplicates from a list: unique = set([1,2,2,3,3]) -> {1,2,3}
  • Students enrolled in Math (A) and Physics (B): A = {"Ali","Beena","Carl"}, B = {"Beena","Deep"}; A & B gives students in both classes -> {"Beena"}
  • Whitelist check: allowed = {"alice","bob"}; if user in allowed: allow login — fast membership test
  • Set comprehension: squares = {x*x for x in range(1,11)} produces unique square numbers
  • Immutable grouping: config_key = frozenset({"DEBUG", "VERBOSE"}) can be used as a dictionary key
🧮 Formulas
  1. \[Cardinality: |A| = len(A)\]
  2. \[Union: A ∪ B ↔ A | B or A.union(B)\]
  3. \[Intersection: A ∩ B ↔ A & B or A.intersection(B)\]
  4. \[Difference: A \ B ↔ A - B or A.difference(B)\]
  5. \[Symmetric difference: A Δ B ↔ A ^ B or A.symmetric_difference(B)\]
  6. \[Subset: A ⊆ B ↔ A.issubset(B) or A <= B\]
📖14

Comprehensions

💻 COMPUTER SCIENCE / IT

Comprehensions

Key Point: [expression for item in iterable]

What are comprehensions?
Comprehensions are compact, readable constructs in Python for creating sequences (lists, sets, dictionaries) or generators from iterables using a single expression. They combine a loop and optional condition(s) into a concise form.

Basic forms and syntax:

  • List comprehension: [expression for item in iterable if condition]
  • Set comprehension: {expression for item in iterable if condition}
  • Dict comprehension: {key_expression: value_expression for item in iterable if condition}
  • Generator expression: (expression for item in iterable if condition)

Examples (explanatory):

# squares of numbers 1..5
squares = [x*x for x in range(1,6)]

# filter even numbers
evens = [x for x in range(1,21) if x % 2 == 0]

# dictionary mapping name -> length
names = ['Anita','Rohit','Maya']
lengths = {name: len(name) for name in names}

# set of unique words from text (lowercased)
text = 'This is a sample. This sample is simple.'
unique_words = {w.strip('.').lower() for w in text.split()}

# flatten a 2D matrix
matrix = [[1,2],[3,4]]
flat = [item for row in matrix for item in row]

# generator to produce large sequence lazily
gen = (x**2 for x in range(10**6))

When to use: Use comprehensions when you can express the transformation or filter in a single clear expression. For very complex logic, use a normal loop or helper function for readability.

Advantages: More concise code, often faster than equivalent loops (because of optimized C-level implementation), and easily readable for simple transformations. For huge datasets where memory matters, prefer generator expressions to list comprehensions.

Notes / Pitfalls:

  • Nested comprehensions can become hard to read—consider using loops for clarity.
  • List comprehensions build the whole list in memory; use generator expressions to save memory for large streams.
  • Side effects in comprehensions (e.g., modifying external variables) are discouraged—comprehensions should be used for transformations, not actions.
📌 Examples
  • List comprehension (simple): [x*2 for x in range(1,6)] # -> [2,4,6,8,10]
  • Conditional filter: [x for x in numbers if x%2==0] # keep evens from 'numbers' list
  • Dict comprehension: {s: len(s) for s in ['apple','mango','kiwi']} # -> {'apple':5,'mango':5,'kiwi':4}
  • Set comprehension for unique items: {word.lower() for word in sentence.split()}
  • Nested comprehension (flatten): [elem for row in matrix for elem in row] # 2D to 1D
  • Generator expression (lazy): sum(x*x for x in range(1000000)) # uses less memory than list
🧮 Formulas
  1. \[[expression for item in iterable]\]
  2. \[[expression for item in iterable if condition]\]
  3. \[[expression for a in iterable1 for b in iterable2]\]
  4. \[{expr for item in iterable if condition} # set comprehension\]
  5. \[{key_expr: value_expr for item in iterable if condition} # dict comprehension\]
  6. \[(expression for item in iterable if condition) # generator expression\]
💻15

File Handling

💻 COMPUTER SCIENCE / IT

File Handling

Key Point: open(filename, mode='r', encoding=None) # returns file object

What is File Handling?
File handling in Python is the process of creating, reading, writing and closing files so programs can store and retrieve persistent data (text or binary) on disk. Files let programs preserve information between runs (for example, logs, user data, configuration, images).

Opening a file
Use open(filename, mode, encoding=None). The function returns a file object you use to perform operations.

Common modes

  • 'r' — read (file must exist)
  • 'w' — write (creates/truncates file)
  • 'a' — append (creates if not exists)
  • 'x' — create only (fails if exists)
  • Add 'b' for binary (e.g., 'rb', 'wb')
  • Add '+' to update (read & write) (e.g., 'r+', 'w+')

Important file methods

  • .read([size]) — read whole file or up to size bytes/characters
  • .readline() — read next line including newline
  • .readlines() — return list of all lines
  • .write(string) — write string to file (returns number of characters)
  • .writelines(list_of_strings) — write multiple strings (no automatic newlines)
  • .seek(offset, whence=0) — move file pointer (whence: 0=start, 1=current, 2=end)
  • .tell() — current file pointer position
  • .close() — close file and free resources

Context manager (recommended)
Using with open(...) as f: ensures the file is closed automatically even if an error occurs.

Text vs Binary
Text mode reads/writes strings and applies newline and encoding handling. Binary mode reads/writes bytes — use for images, audio, executables.

Error handling
Files may not exist or permissions may fail; handle exceptions with try/except or rely on context manager and explicit checks.

When to use file handling (real-life)
Logging, saving user profiles, caching data, reading/writing CSV or JSON, serving or storing images and other media.

Good practices

  • Prefer with to ensure files are closed.
  • Specify encoding='utf-8' for text files where appropriate.
  • Use binary mode for non-text files.
  • Process large files line-by-line (iterator) to avoid memory issues.

📌 Examples
  • 1) Read entire file: with open('notes.txt', 'r', encoding='utf-8') as f: data = f.read() print(data)
  • 2) Read file line-by-line (memory efficient): with open('large_log.txt', 'r') as f: for line in f: process(line) # process each line without loading entire file
  • 3) Write and overwrite a file: with open('output.txt', 'w', encoding='utf-8') as f: f.write('Hello World\n') f.writelines(['Line 2\n', 'Line 3\n'])
  • 4) Append to a file: with open('data.csv', 'a', encoding='utf-8') as f: f.write('4,John Doe,28\n')
  • 5) Copy a binary file (image): with open('photo.jpg', 'rb') as src, open('copy.jpg', 'wb') as dst: while True: chunk = src.read(4096) if not chunk: break dst.write(chunk)
  • 6) Using seek and tell: with open('example.txt', 'r+') as f: print('Start pos', f.tell()) f.seek(10) # move pointer to 10th byte/char f.write('INSERT') print('Now pos', f.tell())
🧮 Formulas
  1. \[open(filename\]
    \[mode='r'\]
    \[encoding=None) # returns file object\]
  2. \[f.read([size]) # read up to size characters/bytes\]
    \[no size => read all\]
  3. \[f.readline() # read single line\]
  4. \[f.readlines() # return list of lines\]
  5. \[f.write(string) # write string (text mode) or bytes in binary mode\]
  6. \[f.writelines(list_of_strings) # write multiple strings\]
💻16

Exception Handling

💻 COMPUTER SCIENCE / IT

Exception Handling

Key Point: Basic template: try: ... except ExceptionType as e: ... else: ... finally: ...

What is an exception? An exception is a runtime error or an unusual condition that disrupts normal program flow (for example: dividing by zero, accessing a missing file, invalid type conversion). Exceptions are different from syntax errors because they occur while the program is running.

Why handle exceptions? To prevent program crashes, provide meaningful error messages, clean up resources (files, network), and control how the program should continue or terminate.

Key constructs in Python

  • try: Block of code to monitor for exceptions.
  • except: Code to run if a specific exception occurs.
  • else: Optional block that runs if no exception occurred in try.
  • finally: Optional block that always runs (used for cleanup) whether an exception occurred or not.
  • raise: Explicitly raise an exception.
  • assert: Debugging aid that raises AssertionError if a condition is false.

Exception propagation: If an exception is not handled in the current function, it propagates (bubbles) up the call stack until a matching except is found. If none is found, the program terminates and prints a traceback.

Best practices:

  • Catch specific exceptions (e.g., except ValueError:) rather than using a bare except:.
  • Keep try blocks small — only wrap the statements that may raise the exception you want to handle.
  • Use finally (or context managers like with) to ensure resources are released.
  • Provide helpful error messages or recovery steps when possible.

Small example (in HTML-friendly form)

try:
    x = int(input('Enter a number: '))
    print('Reciprocal:', 1 / x)
except ValueError:
    print('Please enter a valid integer.')
except ZeroDivisionError:
    print('Cannot take reciprocal of zero.')
else:
    print('Computation succeeded.')
finally:
    print('Execution finished.')
📌 Examples
  • Divide-by-zero: try to compute 1/x when user inputs 0. Use except ZeroDivisionError to inform the user instead of crashing.
  • File handling: open('data.txt') may raise FileNotFoundError. Use try/except to create the file or notify the user; use finally or with statement to close the file.
  • Invalid conversion: int('abc') raises ValueError. Catch ValueError to prompt for valid input or use default value.
  • Raising custom exceptions: raise ValueError('age must be >= 0') to signal invalid function arguments; create custom classes by inheriting from Exception for domain-specific errors.
🧮 Formulas
  1. \[Basic template: try: <code>...</code> except ExceptionType as e: <code>...</code> else: <code>...</code> finally: <code>...</code>\]
  2. \[Raise syntax: raise ExceptionType('message')\]
  3. \[Catch multiple exceptions: except (TypeError\]
    \[ValueError) as e: <code>...</code>\]
  4. \[Custom exception class: class MyError(Exception): pass\]
💻17

Object-Oriented Programming (Basics)

💻 COMPUTER SCIENCE / IT

Object-Oriented Programming (Basics)

Key Point: Class definition: class ClassName(BaseClass):

What is OOP?
Object-Oriented Programming (OOP) is a programming paradigm that organises code around objects — entities that combine state (attributes) and behavior (methods). Python supports OOP, making it easier to model real-world things and build reusable, modular code.

Core concepts (the 4 pillars)

  • Encapsulation — bundling data (attributes) and methods that operate on the data inside a class and restricting direct access. In Python, a single underscore (_name) suggests protected, double underscore (__name) triggers name mangling (pseudo-private).
  • Abstraction — exposing only essential features and hiding internal implementation details (use methods to provide a clean interface).
  • Inheritance — creating a new class (child) from an existing class (parent) to reuse and extend behavior. Syntax: class Child(Parent):
  • Polymorphism — same interface, different implementations. In Python this appears as method overriding in subclasses and duck typing (if it quacks like a duck...).

Basic components

  • Class — a blueprint that defines attributes and methods. Example: class Car:
  • Object (instance) — a concrete occurrence of a class: c = Car()
  • Attributes — variables tied to class (class variables) or object (instance variables)
  • Methods — functions defined inside a class. The first parameter for instance methods is conventionally self, referring to the instance.
  • Constructordef __init__(self, ...): initializes a new object
  • Destructordef __del__(self): (rarely used) runs when an object is garbage-collected
  • Class methods — use @classmethod and take cls as the first parameter; operate on the class itself.
  • Static methods — use @staticmethod; no implicit first argument; utility functions within class namespace.

Simple example (Python)

class BankAccount:
    interest_rate = 0.04   # class variable

    def __init__(self, owner, balance=0):
        self.owner = owner    # instance variable
        self.balance = balance

    def deposit(self, amount):
        self.balance += amount

    def withdraw(self, amount):
        if amount > self.balance:
            raise ValueError('Insufficient funds')
        self.balance -= amount

    @classmethod
    def set_interest(cls, rate):
        cls.interest_rate = rate

    @staticmethod
    def bank_policy():
        return 'Minimum balance 0'

Inheritance & Polymorphism

class Vehicle:
    def move(self):
        print('Moving')

class Car(Vehicle):
    def move(self):            # overriding
        print('Car is driving')

class Boat(Vehicle):
    def move(self):
        print('Boat is sailing')

# Polymorphism in action
for v in (Car(), Boat()):
    v.move()   # different outputs for same method name

Encapsulation example

class Person:
    def __init__(self, name, ssn):
        self.name = name
        self.__ssn = ssn   # name-mangled: pseudo-private

    def get_ssn(self):
        return '***-**-' + str(self.__ssn)[-4:]

When to use OOP? Use OOP when modelling entities with clear attributes and behaviors, when you want reusable and extensible code, and when designing larger systems (GUIs, games, simulations, web back ends).

Common mistakes to avoid

  • Overusing inheritance instead of composition. Prefer composition (has-a) if relationship is not a strict is-a.
  • Exposing internal state freely—use methods or properties to control access.
  • Confusing class variables and instance variables: changing a mutable class variable affects all instances.

Summary: OOP in Python helps map real-world problems into code through classes and objects, promotes code reuse (inheritance), hides complexity (encapsulation/abstraction), and provides flexible behaviour (polymorphism).

📌 Examples
  • BankAccount class: deposit, withdraw, class variable interest_rate, classmethod set_interest, staticmethod bank_policy (see code in explanation).
  • Vehicle inheritance: base class Vehicle with move(); subclasses Car and Boat override move() to demonstrate polymorphism.
  • Library system (real-life): Class Book (title, author, isbn), class Member (name, id), class Loan (book, member, due_date) — composition: Loan has-a Book and has-a Member.
  • Student and Teacher: class Person, subclasses Student and Teacher; Student adds grades, Teacher adds subject — reuse and extension via inheritance.
🧮 Formulas
  1. \[Class definition: class ClassName(BaseClass):\]
  2. \[Constructor: def __init__(self\]
    \[args):\]
  3. \[Create object: obj = ClassName(arguments)\]
  4. \[Call method: obj.method(arguments)\]
  5. \[Class variable: inside class body (shared by all instances)\]
  6. \[Instance variable: self.var in __init__ or methods (unique per instance)\]
💻18

Built-in Functions and Common Utilities

📐 MATHEMATICAL FORMULA / THEOREM

Built-in Functions and Common Utilities

Key Point: print(*objects, sep=' ', end='\n', file=sys.stdout, flush=False) # prints to output

What they are: Built-in functions are pre-defined functions available in Python without importing any module (for example: print, len, sum, type, range). Common utilities are small standard-library modules that are frequently used with basic Python programs (for example: math, random, datetime, os, sys).

Why they matter: They provide fast, tested, and readable ways to perform everyday tasks — iteration, type conversion, aggregation, sorting, I/O, simple math, randomness, and date/time handling — so you don’t need to write these from scratch.

Categories and common uses:

  • Type conversions: int(x), float(x), str(x), bool(x).
  • Sequence utilities: len(), range(), enumerate(), zip(), sorted(), reversed().
  • Aggregation: sum(), min(), max(), any(), all().
  • Functional-style tools: map(), filter(), zip(), filter().
  • Introspection & help: type(), isinstance(), dir(), help(), id().
  • Math & utilities: abs(), pow(), round(), plus the math module for advanced functions.
  • Randomness & time: random for random choices and shuffling; datetime for timestamps, formatting.

Good practices: Prefer built-ins for clarity and speed. Use list comprehensions for simple mapping/filtering when readability is better than chaining map/filter. Avoid eval and exec unless absolutely necessary (security risk).

Example workflow: To compute and display sorted unique student scores you might combine set(), sorted(), and print() together with type conversion from input.

📌 Examples
  • 1) Sum of expenses (aggregation): expenses = [1200, 350, 2000, 450] print('Total =', sum(expenses)) # Total = 3999
  • 2) Filter even numbers and list squares (map/filter): nums = list(range(1, 11)) evens = list(filter(lambda x: x % 2 == 0, nums)) squares = list(map(lambda x: x*x, evens)) print(evens, squares) # [2,4,6,8,10] [4,16,36,64,100]
  • 3) Indexing with enumerate (real-life: display roll numbers): students = ['Asha','Bina','Charu'] for i, name in enumerate(students, start=1): print(i, name) # 1 Asha\n# 2 Bina\n# 3 Charu
  • 4) Pairing related lists with zip (real-life: names with marks): names = ['A','B'] marks = [85, 92] for name, mark in zip(names, marks): print(name, '=>', mark) # A => 85\n# B => 92
  • 5) Generate 6-digit OTP (random utility): import random otp = ''.join(str(random.randint(0,9)) for _ in range(6)) print('OTP:', otp)
  • 6) Current timestamp and formatting (datetime): from datetime import datetime now = datetime.now() print('Timestamp:', now.strftime('%Y-%m-%d %H:%M:%S'))
🧮 Formulas
  1. \[print(*objects\]
    \[sep=' '\]
    \[end='\n'\]
    \[file=sys.stdout\]
    \[flush=False) # prints to output\]
  2. \[input(prompt='') -> str # reads a line from standard input (always returns string)\]
  3. \[len(obj) -> int # returns number of items in a sequence or collection\]
  4. \[range(start\]
    \[stop[\]
    \[step]) # produces an immutable sequence of integers for iteration\]
  5. \[sum(iterable\]
    \[start=0) -> number # adds items of iterable to start\]
  6. \[sorted(iterable, *\]
    \[key=None\]
    \[reverse=False) -> list # returns a new sorted list\]
📊19

Data Structure Operations & Algorithms (Basic)

💻 COMPUTER SCIENCE / IT

Data Structure Operations & Algorithms (Basic)

Key Point: Linear search comparisons (worst-case): n (checks each element).

Overview: Data structures store and organize data so that operations (access, search, insert, delete, update) can be done efficiently. In Class 12 Python basics, focus is usually on built-in structures (list, tuple, set, dict) and simple algorithms for searching and sorting.

Common operations:

  • Traversal: visiting each element (e.g., for i in list: ...). Used for inspection, printing, aggregation.
  • Access: reading an element by index or key (list[i], dict[key]).
  • Search: find whether an element exists and possibly its position (linear/ binary search).
  • Insertion: add an element (list.append(), insert at index, dict[key] = value, set.add()).
  • Deletion: remove an element (del list[i], list.remove(x), dict.pop(key), set.remove(x)).
  • Update: modify an existing element (list[i] = new, dict[key] = new).

Basic algorithms:

  • Linear (Sequential) Search: check elements one by one until found. Works on unsorted data.
  • Binary Search: divide-and-conquer search on sorted arrays—compare middle element and discard half each step.
  • Bubble Sort: repeatedly compare adjacent items and swap if out of order—simple but inefficient.
  • Selection Sort: repeatedly find the minimum (or maximum) remaining element and place it next.
  • Insertion Sort: build a sorted portion by inserting each new element into its correct place—efficient for small or nearly-sorted lists.

When to use which structure:

  • List (mutable sequence): good for ordered collections, indexing, iteration.
    • append() is amortized O(1); insertion/deletion at arbitrary index is O(n).
  • Tuple (immutable sequence): use when data should not change (safer, slightly faster access than lists).
  • Set: unordered collection of unique items; good for membership testing and eliminating duplicates (average O(1)).
  • Dictionary (mapping): key→value pairs; very efficient lookup, insert, delete on average (O(1)).

Complexity intuition (Big-O): understanding how time grows with n (number of elements) is key to choosing algorithms/data structures. See formulas below for common operations.

Simple Python examples (conceptual):

  • Linear search: loop through list until element found.
  • Binary search: keep low, high indices; check mid; update bounds until found or low>high.
  • Bubble sort: nested loops swapping adjacent items if out of order.

Tips for exams:

  • Be explicit whether data is sorted before recommending binary search.
  • State average/worst-case complexities where asked.
  • Know basic built-in methods (append, pop, remove, sort, reversed) and their typical costs.
📌 Examples
  • Linear search in a list of student names: check each name until the required name is found (unsorted list).
  • Binary search for a roll number in a sorted list of roll numbers: faster than linear search for large sorted lists.
  • Use a dictionary to count word frequencies from a text: dict[word] = dict.get(word, 0) + 1 for O(1) updates per word.
  • Use a set to remove duplicate items from a list of submitted answers: unique = set(submissions).
  • Use list.append() to collect inputs and list.sort() or sorted() to sort results before displaying.
🧮 Formulas
  1. \[Linear search comparisons (worst-case): n (checks each element).\]
  2. \[Binary search comparisons (worst-case): floor(log2(n)) + 1 ≈ O(log n).\]
  3. \[Bubble sort comparisons (worst-case): n(n-1)/2 ≈ O(n^2).\]
  4. \[Selection sort comparisons: n(n-1)/2 ≈ O(n^2).\]
  5. \[Insertion sort worst-case time: O(n^2)\]
    \[best-case (already sorted): O(n).\]
  6. \[List access by index: O(1)\]
    \[List insertion/deletion at arbitrary index: O(n).\]
💻20

Debugging and Testing (Basic)

💻 COMPUTER SCIENCE / IT

Debugging and Testing (Basic)

Key Point: Error = Observed result - Expected result (useful for numeric comparisons)

What is Debugging? Debugging is the systematic process of locating, understanding and fixing defects (bugs) in a program so that it behaves as intended. It follows a detective-like workflow: reproduce the problem, isolate the cause, fix the code, and verify the fix.

What is Testing? Testing is the process of executing a program with the intent of finding errors and verifying that the program meets its requirements. Testing helps ensure correctness, reliability and robustness before deployment.

Common types of errors:

  • Syntax errors: mistakes in language grammar (e.g., missing colon, unmatched parentheses). Caught by interpreter at parse time.
  • Runtime errors (exceptions): occur when the program is running (e.g., ZeroDivisionError, IndexError, AttributeError/NoneType).
  • Logical (semantic) errors: program runs but produces incorrect results (e.g., off-by-one in loops, wrong condition).

Basic debugging workflow:

  1. Reproduce the problem reliably (note inputs and steps).
  2. Examine error messages and stack traces.
  3. Isolate the smallest failing part (reduce input, add prints or use a debugger).
  4. Form a hypothesis and change the code to fix it.
  5. Verify by rerunning existing tests and added tests.

Practical debugging techniques:

  • Print statements: quick way to check values and flow (print("value:", x)).
  • Assertions: assert condition, 'message' to enforce assumptions.
  • Interactive debugger/IDE tools: set breakpoints, step into/over, inspect variables and call stack.
  • Logging: record events at different levels (DEBUG/INFO/WARNING/ERROR).
  • Rubber-duck debugging: explain code aloud to find logic mistakes.
  • Bisection: narrow the bug by testing halves of the code or commits (git bisect).

Basic testing strategies:

  • Manual testing: run the program with representative inputs.
  • Unit testing: test small functions independently (in Python, unittest or pytest).
  • Boundary testing: test edge values (0, 1, max, min) where bugs often appear.
  • Equivalence partitioning: group inputs that should behave the same and test one from each group.
  • Regression testing: re-run tests after a fix to ensure no new bugs were introduced.

Test case components:

  • Test input: the data given to the function/program.
  • Expected output: what the correct result should be.
  • Actual output: what the program produced.
  • Result: pass or fail.

Real-life analogy: Debugging is like troubleshooting a broken bicycle: you reproduce the problem (bike wobbles), inspect parts (tires, spokes, axle), isolate the cause (loose spoke), fix it, then test ride to confirm.

Tips for students: read error messages carefully, test small pieces of code, write simple test cases first, use meaningful variable names, and keep functions short so errors are easier to find.

Small illustrative code snippets (see examples below for full examples):

# Logical error example (off-by-one):
def sum_1_to_n(n):
    s = 0
    for i in range(1, n):  # bug: should be range(1, n+1)
        s += i
    return s
📌 Examples
  • Syntax error example: Code: def greet(name) print('Hello', name) Problem: Missing colon after function signature -> SyntaxError: invalid syntax. The interpreter points to the location. Fix: def greet(name): print('Hello', name) Explanation: Always read the interpreter message and correct the grammar (colons, parentheses, indentation).
  • Runtime error example (NoneType / AttributeError): Code: data = {'a': 10} x = data.get('b') print(x.upper()) Problem: data.get('b') returns None, calling .upper() on None raises AttributeError. Fix: x = data.get('b') if x is not None: print(x.upper()) else: print('key missing') Explanation: Check return values before calling methods; use default values: data.get('b', '') to return empty string.
  • Logical error example (off-by-one sum): Buggy code: def sum_1_to_n(n): s = 0 for i in range(1, n): # loop excludes n s += i return s Expected for n=5: 15, Actual: 10 Fix: def sum_1_to_n(n): s = 0 for i in range(1, n+1): s += i return s Explanation: Off-by-one errors are common in loops; test boundary values (n=1, n=0, n=5).
  • Debugging with prints and assertion: Code: def avg(lst): assert len(lst) > 0, 'list must not be empty' total = 0 for x in lst: print('adding', x) # debugging print total += x return total/len(lst) Explanation: Use assert to enforce preconditions and prints to observe the flow. Remove or convert prints to logging after fixing.
🧮 Formulas
  1. \[Error = Observed result - Expected result (useful for numeric comparisons)\]
  2. \[Test coverage (%) = (number of executed test cases / total planned test cases) * 100\]
  3. \[Pass rate (%) = (number of passed tests / total executed tests) * 100\]
  4. \[Defect density = (number of defects found / size of code) * 1000 (defects per KLOC\]
    \[size could be lines of code)\]

Key Concepts

Identifier
Name used to identify variables, functions, classes, etc.; must start with a letter or underscore and can contain letters, digits and underscores. Keywords cannot be used as identifiers.
Keyword
Reserved words in Python that have special meaning and cannot be used as identifiers (e.g., if, for, def, return).
Variable
A named storage that holds a value. Variables are dynamically typed in Python (type determined at runtime).
Data type
Classification of data that tells the interpreter how the data is used (e.g., int, float, str, bool, list).
Type casting
Converting a value from one data type to another using constructors like int(), float(), str().
String
Immutable sequence of characters used to represent text. Supports slicing and many methods.
List
Ordered, mutable collection of items, can contain mixed types and supports indexing and methods like append().
Tuple
Ordered, immutable collection of items. Useful for fixed groups of values and can be used as dictionary keys.
Dictionary
Unordered (insertion-ordered from Python 3.7), mutable collection of key:value pairs used for fast lookup by key.
Set
Unordered collection of unique elements; supports set operations like union, intersection and difference.
Operator
Symbol or keyword that performs operations on operands (arithmetic, relational, logical, membership, bitwise, etc.).
Expression
Combination of values, variables and operators that evaluates to a single value.
Conditional statement
Controls flow using conditions: if, if-elif-else to execute code blocks based on boolean expressions.
For loop
Iterates over items of a sequence (like list, string, range) and executes a block repeatedly.
While loop
Repeats a block of code while a condition is True; may need explicit update to avoid infinite loop.
Function
Reusable block of code defined with def that may accept parameters and optionally return a value.
Recursion
A function calling itself to solve a smaller instance of the same problem; requires a base case.
Module
A file containing Python definitions and statements (functions, classes, variables) that can be imported using import.
File handling
Reading from and writing to files using open(), read(), write(), and close() (or with context manager).
Exception handling
Mechanism to handle runtime errors using try, except, else and finally blocks to prevent program crash.

Practice Questions

  1. Differentiate between a mutable and an immutable data type with one example each. / परिवर्तनीय (mutable) और अपरिवर्तनीय (immutable) डेटा प्रकार में एक-एक उदाहरण सहित अंतर बताइए।
    Show answer

    Mutable objects can be changed in place (e.g., list), while immutable objects cannot be altered after creation (e.g., tuple, str, int). / परिवर्तनीय वस्तुएँ स्थान पर बदली जा सकती हैं (जैसे list), जबकि अपरिवर्तनीय वस्तुएँ बनने के बाद नहीं बदली जा सकतीं (जैसे tuple, str, int)।

  2. What is the output of: print(2 ** 3 ** 2)? Justify with associativity. / print(2 ** 3 ** 2) का आउटपुट क्या होगा? साहचर्यता द्वारा कारण बताइए।
    Show answer

    512, because exponentiation (**) is right-to-left associative, so it evaluates 2 ** (3 ** 2) = 2 ** 9 = 512. / 512, क्योंकि घातांक (**) दायें-से-बायें साहचर्य है, अतः 2 ** (3 ** 2) = 2 ** 9 = 512 का मूल्यांकन होता है।

  3. Given s = 'Anjali', what do s[0], s[-1] and s[1:4] return? / s = 'Anjali' दिया है, तो s[0], s[-1] और s[1:4] क्या लौटाएँगे?
    Show answer

    s[0] returns 'A', s[-1] returns 'i', and s[1:4] returns 'nja' (start inclusive, stop exclusive). / s[0] 'A' लौटाता है, s[-1] 'i' लौटाता है, तथा s[1:4] 'nja' लौटाता है (आरंभ सम्मिलित, अंत वर्जित)।

  4. Why does int('12.3') raise an error while int(12.3) does not? / int('12.3') त्रुटि क्यों देता है जबकि int(12.3) नहीं देता?
    Show answer

    int(12.3) truncates a float to 12, but int('12.3') tries to parse a non-integer string and raises ValueError. / int(12.3) फ्लोट को काटकर 12 कर देता है, परन्तु int('12.3') एक गैर-पूर्णांक स्ट्रिंग को पार्स करने का प्रयास करता है और ValueError देता है।

  5. Write a Python program using a loop to find the factorial of a number n. / किसी संख्या n का क्रमगुणित (factorial) ज्ञात करने हेतु लूप का प्रयोग कर पायथन प्रोग्राम लिखिए।
    Show answer

    fact = 1\nfor i in range(1, n+1):\n fact *= i\nprint(fact) # e.g. n=5 gives 120. / fact=1; for i in range(1,n+1): fact*=i; print(fact) — जैसे n=5 पर 120 मिलता है।

  6. What is aliasing? Predict the output: a=[1,2]; b=a; b.append(3); print(a). / उपनामकरण (aliasing) क्या है? आउटपुट बताइए: a=[1,2]; b=a; b.append(3); print(a).
    Show answer

    Aliasing means two names refer to the same object; since b and a point to one list, output is [1, 2, 3]. / उपनामकरण अर्थात् दो नाम एक ही वस्तु को संदर्भित करते हैं; b व a एक ही सूची को इंगित करते हैं, अतः आउटपुट [1, 2, 3] है।

  7. Distinguish between the == and is operators in Python. / पायथन में == और is संकारकों में अंतर बताइए।
    Show answer

    == checks value equality (whether two objects have equal values), while is checks identity (whether they are the same object in memory). / == मान समानता जाँचता है (क्या दो वस्तुओं के मान समान हैं), जबकि is पहचान जाँचता है (क्या वे स्मृति में एक ही वस्तु हैं)।

  8. Explain short-circuit evaluation of the 'and' operator with an example. / 'and' संकारक के लघु-परिपथ मूल्यांकन को उदाहरण सहित समझाइए।
    Show answer

    In 'A and B', if A is False, B is not evaluated since the result is already False; e.g., fast_check() and expensive_check() runs the second only if the first is True. / 'A and B' में यदि A असत्य है तो B का मूल्यांकन नहीं होता क्योंकि परिणाम पहले ही असत्य है; जैसे fast_check() and expensive_check() में दूसरा तभी चलता है जब पहला सत्य हो।

Related Laws & Principles

Explore all

Foundational laws & principles connected to this chapter — tap to open in the Laws Explorer.

Loading related laws…
Sourced from 273 content files · LLOS Learn · browse all chapters