UNIT 3: Python Programming - Intermediate Concepts & Practical Application
3.1. Object-Oriented Programming (OOP) - The Paradigm Shift
3.1.1. Core Concepts & Motivation
-
Class: A blueprint/template for creating objects. Defines attributes (data) and methods (functions).
-
Object (Instance): A concrete realization of a class. Each object has its own state (attribute values).
-
__init__()Method: The constructor. Called automatically when a new object is created (obj = ClassName()). Used to initialize instance attributes.class Student: def __init__(self, name, roll_no): # Constructor self.name = name # Instance attribute self.roll_no = roll_no
3.1.2. Defining Classes & Creating Objects
-
Syntax:
class ClassName(ParentClass):(ParentClass is optional for inheritance). -
selfParameter: The first parameter of any instance method. Refers to the specific object instance on which the method is called. Python passes it automatically.s1 = Student("Alice", 101) # __init__(self, "Alice", 101) is called print(s1.name) # Output: Alice
3.1.3. Key OOP Principles
| Principle | Concept | Python Mechanism | Key Idea |
|---|---|---|---|
| Encapsulation | Bundling data + methods; restricting direct access. | Naming conventions: _var (protected), __var (name mangling). @property for getters/setters. |
Hide internal state, expose controlled interface. |
| Inheritance | Creating new classes (child) from existing ones (parent). | class Child(Parent): |
Promotes code reuse. Child inherits parent's attributes/methods. |
| Method Overriding | Child defines a method with the same name as parent's. | Child's version is called on child objects. | |
super() |
super().__init__(params) calls the parent's constructor/method. |
Enables cooperative multiple inheritance. | |
| Polymorphism | "Many forms". Same operation behaves differently on different types. | Duck Typing: "If it walks like a duck...". No explicit interface checks. | len(obj) works for list, string, custom class with __len__. |
| Abstraction | Hiding complex implementation, showing only essentials. | Achieved via encapsulation and well-defined interfaces. | Focus on what an object does, not how. |
[!TIP] Common Pitfall: Forgetting
selfas the first parameter in instance methods causesTypeError.__init__must returnNone.
3.2. Advanced Functions & Scoping
3.2.1. Lambda Functions
-
Definition: Small, anonymous, single-expression functions.
-
Syntax:
lambda arguments: expression -
Use Cases: Short functions for
map(),filter(),sorted(key=),tkintercallbacks.square = lambda x: x**2 nums = [1, 2, 3] squares = list(map(lambda x: x**2, nums)) # [1, 4, 9] sorted(students, key=lambda s: s.gpa) # Sort by GPA
[!TIP] Rule: Lambda can only contain an expression, not statements (like
if-elseblocks,forloops). Use a regulardeffor complex logic.
3.2.2. Comprehensions & Generator Expressions
| Type | Syntax | Result Type | Evaluation |
|---|---|---|---|
| List | [expr for item in iterable if cond] |
list |
Eager (builds full list) |
| Dict | {key: val for item in iterable} |
dict |
Eager |
| Set | {expr for item in iterable} |
set |
Eager |
| Generator | (expr for item in iterable) |
generator |
Lazy (yields values on-demand) |
gen = (x**2 for x in range(5)) # Creates generator object
print(next(gen)) # 0
print(next(gen)) # 1 (computed only when needed)
3.2.3. Variable Scope & Namespaces (LEGB Rule)
Python resolves names by searching scopes in this order:
-
Local: Inside current function.
-
Enclosing: In enclosing (outer) function scopes.
-
Global: At the top level of the module/file.
-
Built-in: In Python's built-in names (e.g.,
len,print).
-
globalkeyword: Modify a global variable from within a function.count = 0 def inc(): global count count += 1 # Now modifies global 'count' -
nonlocalkeyword: Modify a variable from an enclosing (non-global) scope.def outer(): x = 10 def inner(): nonlocal x x = 20 # Modifies 'x' in outer() inner() print(x) # 20
3.3. Error Handling & Exceptions
3.3.1. Understanding Exceptions
-
Syntax Errors: Code structure violations (caught by parser). Not exceptions.
-
Exceptions: Runtime errors. Occur during execution.
- Common Built-ins:
ValueError,TypeError,IndexError,KeyError,FileNotFoundError,IOError,ZeroDivisionError,Exception(base for all user-defined).
- Common Built-ins:
3.3.2. Try-Except Blocks
try:
# Code that might raise an exception
result = 10 / 0
except ZeroDivisionError as e:
# Handle specific exception
print(f"Cannot divide by zero: {e}")
except (TypeError, ValueError):
# Handle multiple exceptions
print("Type or value error occurred.")
except Exception as e:
# Catch-all (use cautiously)
print(f"Unexpected error: {e}")
else:
# Executes ONLY if try block had NO exception
print("Operation successful.")
finally:
# ALWAYS executes (cleanup: close files, release resources)
print("Cleanup complete.")
[!TIP] Order Matters: Catch specific exceptions before general ones (
Exception).finallyruns even if an exception is caught or uncaught (but not onsys.exit()or keyboard interrupt).
3.3.3. Raising Exceptions
-
raise: Signal an error condition.def set_age(age): if age < 0: raise ValueError("Age cannot be negative") self.age = age -
Re-raising: Use
raisewithout arguments inside anexceptblock to propagate the caught exception up the call stack.
3.4. File Input/Output (I/O) & Data Persistence
3.4.1. Working with Text Files
-
Opening Files:
open(filename, mode)- Modes:
'r'(read),'w'(write, truncate),'a'(append),'r+'(read/write),'b'(binary, e.g.,'rb').
- Modes:
-
Context Manager (
withstatement): BEST PRACTICE. Automatically closes file, even on errors.with open('data.txt', 'r') as f: content = f.read() # Read entire file # f is automatically closed here -
Reading Methods:
-
f.read(size): Readsizebytes/entire file. -
f.readline(): Read one line (including\n). -
f.readlines(): Read all lines into a list.
-
-
Writing Methods:
-
f.write(string): Write a string. -
f.writelines(list_of_strings): Write multiple strings (no newlines added automatically).
-
3.4.2. Working with Structured Data
| Format | Module | Key Functions | Notes |
|---|---|---|---|
| CSV | csv |
csv.reader(f), csv.writer(f) |
Handles commas, quotes. Use with on file. |
| JSON | json |
json.load(f) (read), json.dump(obj, f) (write) |
Converts between Python objects (dict, list) and JSON strings. indent for pretty-print. |
| Pickle | pickle |
pickle.dump(obj, f), pickle.load(f) |
Serializes ANY Python object. SECURITY RISK: Never unpickle data from untrusted sources. |
3.5. Modules, Packages, and the Standard Library
3.5.1. Modular Programming
-
Module: A
.pyfile containing Python definitions and statements. -
Importing:
import module # Use: module.func() from module import func # Use: func() from module import * # Use: all public names (discouraged) -
if __name__ == "__main__":idiom: Code inside this block runs only when the file is executed directly (not when imported as a module). Used for test code or demo.
3.5.2. Packages
-
Package: A directory containing:
-
Module files (
.py). -
A special
__init__.pyfile (can be empty). This tells Python the directory is a package.
-
-
Hierarchical Import:
from package.subpackage import module
3.5.3. Key Standard Library Modules (Examples)
| Module | Purpose | Example |
|---|---|---|
os / os.path |
OS interactions (dirs, paths, env vars). | os.getcwd(), os.path.join(a, b) |
sys |
System params, command-line args. | sys.argv, sys.exit() |
datetime |
Date/time objects & arithmetic. | datetime.datetime.now() |
math |
Mathematical functions (floor, sqrt, trig). | math.pi, math.log10() |
random |
Pseudo-random number generation. | random.randint(1, 10), random.choice(list) |
collections |
Specialized containers. | collections.Counter, collections.defaultdict |
itertools |
Efficient looping/iteration tools. | itertools.permutations(), itertools.chain() |
3.6. Introduction to Virtual Environments & Package Management
3.6.1. Why Virtual Environments?
Isolate project dependencies. Prevents version conflicts between projects (e.g., Project A needs numpy==1.20, Project B needs numpy==1.24).
3.6.2. Using venv
# Create a virtual environment named 'venv' in current directory
python -m venv venv
# Activate (Linux/macOS)
source venv/bin/activate
# Activate (Windows)
venv\Scripts\activate
# Deactivate (any OS)
deactivate
[!TIP] Naming Convention: Common to name the environment directory
venvor.venvand add it to.gitignore.
3.6.3. Using pip
| Command | Purpose |
|---|---|
pip install package_name |
Install latest version from PyPI. |
pip install package_name==1.2.3 |
Install specific version. |
pip list |
List all installed packages in current environment. |
pip freeze > requirements.txt |
Export exact versions of all installed packages. |
pip install -r requirements.txt |
Install packages from a requirements file. |
pip uninstall package_name |
Remove a package. |
[!TIP] Critical: Always activate the correct virtual environment before running
pip install.pipinstalls to the currently active environment.