INT108Semester 1 • 4 CreditsCore Subjects

Python Programming

This course introduces Python programming fundamentals and covers conditional and iterative statements, functions and recursion, core data structures, object-oriented programming, file handling, exceptions, and regular expressions.

6 Units • Notes • Model Answers • MCQs
Select Course Unit (6 Units)
Active: Unit 1
Unit 1:Python Fundamentals and Environment Setup
28 min read•High-Yield Unit Guide

Python Fundamentals and Environment Setup

Unit 1 Exam Focus & Core Takeaways

Review the core definitions, standard architectures, and syntax patterns below. Pay special attention to sections highlighted with bullet points for your mid-term and end-term subjective questions.

Unit 1: Python Fundamentals and Environment Setup

1. Python Architecture, Design Philosophy, and Execution Model

Python is a high-level, interpreted, dynamically typed, and garbage-collected programming language conceived by Guido van Rossum in 1989 and officially released in 1991. The language adheres to the design philosophy outlined in PEP 20 (The Zen of Python), emphasizing code readability, explicit logic, syntactic simplicity, and developer productivity:

  • "Beautiful is better than ugly."
  • "Explicit is better than implicit."
  • "Simple is better than complex."
  • "Readability counts."

1.1 The CPython Two-Stage Execution Model

Although colloquially termed an "interpreted" language, standard Python (specifically the reference implementation CPython) executes a hybrid compilation and virtual-machine interpretation model:

CODE
                  CPython Source-to-Execution Pipeline
       +-----------------------+
       |   Source Code (.py)   |
       +-----------------------+
                   |
                   v  (Parser & Bytecode Compiler)
       +-----------------------+
       | Bytecode (.pyc cache) |  e.g., __pycache__/script.cpython-312.pyc
       +-----------------------+
                   |
                   v  (Virtual Machine Dispatch Loop)
       +-----------------------+
       | Python Virtual Machine|  (Stack-based PVM executes bytecode opcodes)
       |        (PVM)          |
       +-----------------------+
                   |
                   v
       +-----------------------+
       | CPU / OS Native Exec  |
       +-----------------------+
  1. Bytecode Compilation:
    • When a Python script or module is imported or executed, the CPython compiler parses the syntax tree and emits platform-independent bytecode (sequences of 16-bit or 8-bit opcodes such as LOAD_FAST, BINARY_OP, STORE_NAME).
    • Bytecode files are cached automatically in the __pycache__/ directory with the .pyc extension to avoid re-compilation on subsequent runs if source timestamps match.
  2. Virtual Machine Interpretation:
    • The Python Virtual Machine (PVM) is a stack-based runtime interpreter written in C.
    • It iterates through the compiled bytecode stream within a massive evaluation loop (_PyEval_EvalFrameDefault), executing opcodes, managing runtime call frames, and invoking native OS system calls.

2. Environment Setup, CLI Tools, and Execution Modes

Developing in Python 3 requires a properly configured runtime environment, system path routing, and familiarity with command-line interfaces.

2.1 The System PATH Environment Variable

  • On Windows and Unix operating systems, the PATH environment variable contains an ordered list of directory paths where the operating system searches for executable binaries.
  • If the directory containing python.exe and its companion Scripts/ folder (where pip resides) is omitted from PATH, the command prompt will report:
    'python' is not recognized as an internal or external command, operable program or batch file.
  • Modern Windows installers provide an option to "Add Python to PATH" or install the Python Launcher (py.exe) into C:\Windows, allowing execution independent of specific path entries.

2.2 The Windows Python Launcher (py.exe)

The Python Launcher manages multiple side-by-side installations of Python (e.g., Python 3.10, 3.11, 3.12, 32-bit vs. 64-bit):

  • py -0 or py --list: Lists all installed Python versions detected on the host system.
  • py -0p or py --list-paths: Displays registered runtimes alongside their exact executable file paths.
  • py -3.11 script.py: Explicitly launches script.py using the installed Python 3.11 runtime.
  • Shebang Line Handling: If a script starts with #!python3 or #!/usr/bin/env python3, py.exe automatically parses the directive and selects the corresponding interpreter.

2.3 Interactive Mode vs. Script Mode

  1. Interactive Mode (REPL - Read-Eval-Print Loop):
    • Launched by invoking python or py without command-line script arguments.
    • Prompts the user with primary prompt >>> (and secondary prompt ... for multi-line blocks).
    • Reads an expression, compiles it in memory, evaluates it immediately, and prints non-None return values to stdout. Ideal for rapid experimentation and debugging.
  2. Script Mode:
    • Executes an entire saved text file: python script.py.
    • Executes statements sequentially from line 1 to EOF. Does not print expression outcomes unless explicitly wrapped in print().

3. Python Syntax Fundamentals: Indentation, Identifiers, and Keywords

3.1 Significant Whitespace and Indentation

Unlike C, C++, or Java that rely on curly braces {} to demarcate code blocks, Python enforces significant whitespace indentation:

  • Every nested block (body of if, for, while, def, class) must be indented relative to its header statement.
  • PEP 8 Standard: Enforces 4 spaces per indentation level. Mixing tabs and spaces triggers an IndentationError: unindent does not match any outer indentation level or TabError: inconsistent use of tabs and spaces in indentation.
  • A colon (:) at the end of a statement header indicates that an indented suite follows immediately.
python
# Correct block structure using 4 spaces
def compute_magnitude(x, y):
    if x > 0:
        result = (x**2 + y**2) ** 0.5
        return result
    else:
        return 0.0

3.2 Rules for Valid Identifiers

An identifier is a user-defined name assigned to variables, functions, classes, modules, or packages.

  1. Must begin with an uppercase or lowercase ASCII letter (a-z, A-Z) or an underscore (_).
  2. Subsequent characters may include letters, digits (0-9), or underscores.
  3. Cannot begin with a digit (e.g., 2var is a SyntaxError, whereas var2 is valid).
  4. Python is strictly case-sensitive: Total, total, and TOTAL represent three distinct identifiers.
  5. Cannot be identical to any reserved Python keyword.

3.3 Reserved Python Keywords

Python 3 reserves 35 keywords that possess fixed grammatical meaning in the grammar engine. They cannot be used as identifier names:

python
import keyword
print(keyword.kwlist)
# ['False', 'None', 'True', 'and', 'as', 'assert', 'async', 'await', 
#  'break', 'class', 'continue', 'def', 'del', 'elif', 'else', 'except', 
#  'finally', 'for', 'from', 'global', 'if', 'import', 'in', 'is', 
#  'lambda', 'nonlocal', 'not', 'or', 'pass', 'raise', 'return', 'try', 
#  'while', 'with', 'yield']

Note: True, False, and None are capitalized; all other keywords are strictly lowercase.


4. The Python Object Model: Variables, References, and Dynamic Typing

4.1 Variables as Reference Names

In low-level languages like C, a variable represents a fixed chunk of named memory where raw binary bits are stored. In Python, variables are reference tags (pointers) bound to heap-allocated objects:

CODE
      Variable Binding in Python Memory
      Variable Name (Namespace Tag)        Heap-Allocated PyObject
            [ x ] ------------------------> +-----------------------+
                                            | ob_refcnt: 1          |
                                            | ob_type  : <class int>|
                                            | ob_digit : 42         |
                                            +-----------------------+
  • When you write x = 42, Python allocates an integer object representing 42 in heap memory and binds the name x to point to it.
  • Executing y = x does not duplicate the integer; it simply binds y to the same identical object in memory.
  • Built-in function id(obj) returns the unique memory address integer of the object in CPython.
  • Identity operator is verifies whether two reference variables point to the exact same physical memory address:
    python
    a = [1, 2, 3]
    b = a
    c = [1, 2, 3]
    print(a == c)  # True  (Value equality check)
    print(a is c)  # False (Distinct memory objects)
    print(a is b)  # True  (Identical reference target)
    

4.2 Dynamic Typing vs. Strong Typing

  • Dynamic Typing: Variable names possess no intrinsic data type. A name can be rebound to an object of a completely different type at runtime without declarations:
    python
    data = 100        # data references an int
    data = "Active"   # data now references a str
    
  • Strong Typing: Python does not automatically coerce incompatible types in operations. For example, 'Total: ' + 50 raises a TypeError: can only concatenate str (not "int") to str, preventing silent data corruption.

4.3 Mutability vs. Immutability

Every Python object is classified as either mutable or immutable:

  • Immutable Objects: State cannot be modified in-place after instantiation. Modifying them creates a new object in memory:
    • int, float, complex, bool, str, tuple, frozenset, bytes.
  • Mutable Objects: Internal contents can be altered in-place without changing memory address (id()):
    • list, dict, set, bytearray, custom user-defined class instances.

5. Primitive Data Types in Python 3

Data TypeDescriptionConstructor / Literal SyntaxKey Characteristics
intArbitrary-precision integerx = 10, x = -500, x = int("42")No overflow limit; grows dynamically to consume available RAM.
floatDouble-precision floating-pointy = 3.14159, y = 1.5e-3Implemented as C double (IEEE 754 64-bit; ~15-17 decimal digits precision).
complexComplex numbers (a+bja + bj)z = 2 + 3j, z.real, z.imagFormed with real and imaginary parts using suffix j or J.
boolBoolean truth valueflag = True, flag = FalseSubclass of int (issubclass(bool, int) is True). True == 1, False == 0.
strImmutable text sequences = "Hello", s = 'World', s = '''Multiline'''Encoded as Unicode codepoints (UTF-8 / UCS-4 internally).
NoneTypeAbsence of value / nullresult = NoneSingleton object representing no return value or uninitialized state.

5.1 Arbitrary-Precision Integers

Unlike C/C++ where integers overflow at 32-bit (231−1=2,147,483,6472^{31}-1 = 2,147,483,647) or 64-bit boundaries, Python 3 integers automatically scale their bit representation dynamically:

python
big = 2 ** 100
# 1267650600228229401496703205376 (Calculated accurately with zero overflow)

5.2 Truth Value Testing (Truthy vs. Falsy Values)

Any Python object can be evaluated in a boolean context (e.g., if condition:).

  • Falsy Values:
    • Constants: None, False.
    • Numeric zero: 0, 0.0, 0j, Decimal(0), Fraction(0, 1).
    • Empty collections/sequences: "" (empty string), () (empty tuple), [] (empty list), {} (empty dict), set() (empty set), range(0).
  • Truthy Values:
    • Any non-zero number (e.g., -1, 0.0001).
    • Any non-empty string (e.g., "False", " ", "0" are all truthy).
    • Any populated container (e.g., [0], (False,)).

6. Basic Input and Output Operations

6.1 The print() Built-In Function

The print() function formats and writes text to the standard output stream (sys.stdout):

python
print(*objects, sep=' ', end='\n', file=sys.stdout, flush=False)
  • *objects: Zero or more expressions separated by commas. Each object is internally converted to a string using str().
  • sep: String inserted between adjacent printed arguments (default is a single space ' ').
  • end: String appended at the very end of the output (default is a newline character '\n').
  • flush: Boolean specifying whether the output stream buffer should be flushed immediately to the console without buffering.
python
# Demonstrating custom separation and end terminator
print("2026", "10", "15", sep="-", end=" | ")
print("Process Completed")
# Output: 2026-10-15 | Process Completed

6.2 The input() Built-In Function

The input([prompt]) function pauses script execution, prints the optional prompt string to standard output, and reads a single line of text from standard input until the user presses Enter:

  • Critical Principle: input() always returns a string (str), even if the user types numeric digits.
  • To use the entered value in arithmetic calculations, it must be explicitly cast using constructor functions:
    python
    age = int(input("Enter your age: "))       # Type cast to integer
    height = float(input("Enter height in m: ")) # Type cast to float
    
  • If the user enters a non-digit string into int(), Python raises a ValueError: invalid literal for int() with base 10.

7. Arithmetic Operators and Evaluation Precedence

Python provides a comprehensive set of arithmetic operators governed by mathematical precedence rules:

OperatorOperationExampleResultEvaluation Notes
+Addition7 + 310Supports numeric sum and sequence concatenation.
-Subtraction7 - 34Binary subtraction and unary negation (-x).
*Multiplication7 * 321Supports numeric multiplication and sequence repetition.
/True Division7 / 23.5Always returns a float, even if evenly divisible (4 / 2 -> 2.0).
//Floor Division7 // 23Rounds down towards −∞-\infty (-7 // 2 -> -4).
%Modulo (Remainder)7 % 31Follows formula: r=x−(x//y)∗yr = x - (x // y) * y (-7 % 3 -> 2).
**Exponentiation2 ** 38Right-associative: 2 ** 3 ** 2 = 2 ** 9 = 512.

7.1 Operator Precedence Hierarchy (Highest to Lowest)

  1. Parentheses: (...) (Forces explicit sub-expression evaluation).
  2. Exponentiation: ** (Evaluated right-to-left: 4 ** 3 ** 2 = 4 ** (3 ** 2) = 4 ** 9 = 262144).
  3. Unary Operators: +x, -x, ~x.
  4. Multiplicative Group: *, /, //, % (Evaluated left-to-right).
  5. Additive Group: +, - (Evaluated left-to-right).
python
# Evaluating precedence step-by-step:
expr = 3 + 4 * 2 ** 2
# Step 1 (Exponentiation): 2 ** 2 = 4
# Step 2 (Multiplication): 4 * 4 = 16
# Step 3 (Addition)      : 3 + 16 = 19

8. Common Elementary Errors and Debugging Essentials

  1. SyntaxError: Code violates the structural grammar rules of the Python language. Occurs during parsing before execution begins (e.g., missing colon, mismatched parentheses).
  2. IndentationError: A subclass of SyntaxError caused by improper alignment of block suites or mixing tabs and spaces.
  3. NameError: Attempting to reference an identifier variable or function name that has not yet been declared, assigned, or imported in the current namespace scope.
  4. TypeError: Applying an operation or function to an object of inappropriate type (e.g., adding str and int, or passing 3 arguments to a function expecting 2).
  5. ValueError: An operation or function receives an argument that has the correct data type but an inappropriate value (e.g., int("twenty")).
  6. ZeroDivisionError: Attempting to divide, floor-divide, or modulo any number by zero (x/0x / 0).