Python-1

Python Revision Notes - Comprehensive Study Guide

Section 1: Python Environment Setup

4. Different Ways of Creating Python Environment

[image:1]

Python environments help isolate dependencies and prevent conflicts between different projects.

Virtual Environment (venv)^1

  • Purpose: Create isolated Python environments
  • Creation: python -m venv myenv
  • Activation:
  • Windows: myenv\Scripts\activate
  • Linux/Mac: source myenv/bin/activate
  • Deactivation: deactivate
  • Usage: Best for pure Python projects
  • Example:
# Create environment
python -m venv project_env

# Activate (Windows)
project_env\Scripts\activate

# Install packages
pip install requests numpy

# Deactivate
deactivate

Conda Environment^2

  • Purpose: Package and environment management for multiple languages
  • Creation: conda create --name myenv python=3.9
  • Activation: conda activate myenv
  • Package installation: conda install numpy
  • Deactivation: conda deactivate
  • Usage: Best for data science projects
  • Example:
# Create environment with specific Python version
conda create --name data_science python=3.9

# Activate environment
conda activate data_science

# Install packages
conda install numpy pandas matplotlib

# List environments
conda env list

Pipenv^4

  • Purpose: Combines pip and virtualenv functionality
  • Creation: pipenv install (creates Pipfile)
  • Activation: pipenv shell
  • Package installation: pipenv install package_name
  • Usage: Modern dependency management
  • Example:
# Initialize project
pipenv install

# Install package
pipenv install requests

# Enter shell
pipenv shell

# Install from Pipfile
pipenv install --dev

5. Solve-Conda Not Recognized Issue

Common Solutions:

  • Add to PATH: Add Anaconda/Miniconda to system PATH variable^5
  • Reinstall: Download from official Anaconda website
  • Use Anaconda Prompt: Launch from Start menu instead of regular command prompt
  • Manual PATH setup:
  • Windows: Add C:\Users\username\Anaconda3\Scripts to PATH
  • Check installation: conda --version

Section 2: Python Basics

6. Python Basics - Syntax and Semantics

[image:1]

Python Syntax^6

  • Definition: Set of rules dictating how code is written
  • Key Features:
  • Uses English keywords and punctuation
  • Indentation-based structure
  • Case-sensitive language
  • No semicolons required

Python Semantics^6

  • Definition: Defines how code is executed and behavior of constructs
  • Includes: Variable scope, function calls, object references, data type behavior

Error Types^6:

  • Syntax Error: Code doesn't follow language rules
  • Example: print("Hello" (missing closing parenthesis)
  • Runtime Error: Program runs but encounters execution problems
  • Example: Division by zero
  • Logic Error: Code runs but produces incorrect results
  • Example: Using + instead of * in calculations

Example:

# Correct syntax and semantics
name = "Python"  # Variable assignment
print(f"Hello {name}!")  # String formatting

# Case sensitivity demonstration
Name = "Java"  # Different variable
print(name)    # Outputs: Python
print(Name)    # Outputs: Java

7. Variables in Python

Variable Definition^7:

  • Concept: Containers to hold information
  • Assignment: Use = operator
  • Naming Convention: snake_case (lowercase with underscores)

Examples:

# Basic variable assignment
my_name = "Paige"           # String
age = 25                    # Integer
height = 5.8                # Float
is_student = True           # Boolean

# Multiple assignment
x, y, z = 1, 2, 3

# Same value to multiple variables
a = b = c = 10

# Variable reassignment
score = 85
score = score + 5  # Now 90

8. Basic DataTypes in Python

Primary Data Types^7:

Integer (int)

  • Description: Whole numbers
  • Example: age = 25
  • Operations: Arithmetic operations

Float

  • Description: Decimal numbers
  • Example: price = 19.99
  • Operations: Mathematical calculations

String (str)

  • Description: Text data wrapped in quotes
  • Example: message = "Hello World"
  • Operations: Concatenation, slicing, formatting

Boolean (bool)

  • Description: True or False values
  • Example: is_active = True
  • Operations: Logical operations

Examples:

# Integer operations
num1 = 10
num2 = 3
print(num1 + num2)      # 13
print(num1 // num2)     # 3 (floor division)

# String operations
first_name = "John"
last_name = "Doe"
full_name = first_name + " " + last_name
print(len(full_name))   # 8

# Boolean operations
is_valid = True
is_expired = False
result = is_valid and not is_expired  # True

# Type checking
print(type(25))         # <class 'int'>
print(type(3.14))       # <class 'float'>

9. Operators in Python

[image:1]

Arithmetic Operators^8:

  • + Addition: 5 + 3 = 8
  • - Subtraction: 7 - 2 = 5
  • * Multiplication: 4 * 6 = 24
  • / Division: 10 / 2 = 5.0
  • // Floor Division: 5 // 3 = 1
  • % Modulus: 10 % 3 = 1
  • ** Exponentiation: 5 ** 3 = 125

Comparison Operators^8:

  • == Equal to: 5 == 3 → False
  • != Not equal: 5 != 3 → True
  • > Greater than: 5 > 3 → True
  • < Less than: 5 < 3 → False
  • >= Greater than or equal: 5 >= 3 → True
  • <= Less than or equal: 5 <= 3 → False

Logical Operators^8:

  • and Both conditions true: (5 > 3) and (3 > 1) → True
  • or Either condition true: (5 > 3) or (3 < 1) → True
  • not Inverts result: not (5 > 3) → False

Assignment Operators^8:

  • = Assign: x = 5
  • += Add and assign: x += 1 (equivalent to x = x + 1)
  • -= Subtract and assign: x -= 2
  • *= Multiply and assign: x *= 4
  • /= Divide and assign: x /= 2

Examples:

# Arithmetic operations
x = 10
y = 3
print(f"Addition: {x + y}")        # 13
print(f"Modulus: {x % y}")         # 1
print(f"Power: {x ** y}")          # 1000

# Comparison in conditional
age = 18
if age >= 18:
    print("Adult")
else:
    print("Minor")

# Logical operators
temperature = 25
humidity = 60
if temperature > 20 and humidity < 70:
    print("Good weather conditions")

# Assignment operators
counter = 0
counter += 5    # counter is now 5
counter *= 2    # counter is now 10

Section 3: Python Control Flow

10. Conditional Statements (if, elif, else)

[image:2]

Basic if Statement^9:

  • Syntax: Tests a condition and executes code if true
  • Structure: if condition:
  • Indentation: Required for code blocks

if-elif-else Chain^9:

  • elif: Short for "else if", tests additional conditions
  • else: Executes when no previous conditions are true
  • Multiple conditions: Can have multiple elif statements

Examples:

# Simple if statement
score = 85
if score >= 80:
    print("Excellent grade!")

# if-elif-else chain
grade = 87
if grade >= 90:
    letter = "A"
elif grade >= 80:
    letter = "B"
elif grade >= 70:
    letter = "C"
elif grade >= 60:
    letter = "D"
else:
    letter = "F"
print(f"Your grade is: {letter}")

# Nested conditions
age = 20
has_license = True
if age >= 18:
    if has_license:
        print("Can drive legally")
    else:
        print("Need to get a license")
else:
    print("Too young to drive")

# Multiple conditions
temperature = 22
weather = "sunny"
if temperature > 20 and weather == "sunny":
    print("Perfect day for outdoor activities!")

11. Loops in Python

For Loops^11:

  • Purpose: Iterate over sequences (lists, strings, ranges)
  • Syntax: for item in sequence:
  • Usage: When you know the number of iterations

While Loops^12:

  • Purpose: Continue execution while condition is true
  • Syntax: while condition:
  • Usage: When iterations depend on a condition
  • Warning: Must update condition to avoid infinite loops

Loop Control Statements:

  • break: Exit loop immediately
  • continue: Skip current iteration, continue with next
  • else: Execute when loop completes normally (not broken)

Examples:

# For loop with range
for i in range(5):
    print(f"Count: {i}")  # 0, 1, 2, 3, 4

# For loop with list
fruits = ["apple", "banana", "cherry"]
for fruit in fruits:
    print(f"I like {fruit}")

# For loop with string
word = "Python"
for letter in word:
    print(letter.upper())

# While loop
count = 0
while count < 5:
    print(f"Count is: {count}")
    count += 1  # Important: update condition variable

# Loop with break and continue
numbers = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
for num in numbers:
    if num == 3:
        continue    # Skip 3
    if num == 8:
        break      # Stop at 8
    print(num)     # Prints: 1, 2, 4, 5, 6, 7

# While loop with else
i = 1
while i <= 3:
    print(i)
    i += 1
else:
    print("Loop completed normally")

# Nested loops
for i in range(3):
    for j in range(2):
        print(f"i={i}, j={j}")

Section 4: Data Structures Using Python

12. Lists and List Comprehension in Python

[image:2]

Lists^13:

  • Definition: Ordered, mutable sequences for storing collections
  • Creation: Square brackets []
  • Features: Can store different data types, indexable, dynamic size

List Operations:

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

# Accessing elements
print(fruits[^0])        # "apple" (first element)
print(fruits[-1])       # "cherry" (last element)

# Modifying lists
fruits.append("date")          # Add to end
fruits.insert(1, "blueberry")  # Insert at index 1
fruits.remove("banana")        # Remove specific item
popped = fruits.pop()          # Remove and return last item

# List methods
numbers.extend([6, 7, 8])      # Add multiple items
numbers.sort()                 # Sort in place
numbers.reverse()              # Reverse order
print(len(numbers))            # Get length

# Slicing
print(numbers[1:4])            # Elements from index 1 to 3
print(numbers[:3])             # First 3 elements
print(numbers[2:])             # From index 2 to end

List Comprehension^14:

  • Definition: Concise way to create lists based on existing lists
  • Syntax: [expression for item in iterable if condition]
  • Benefits: More readable and efficient than traditional loops

List Comprehension Examples:

# Basic list comprehension
numbers = [i for i in range(10)]           # [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
squares = [x**2 for x in range(5)]         # [0, 1, 4, 9, 16]

# With condition
even_numbers = [x for x in range(20) if x % 2 == 0]  # [0, 2, 4, 6, 8, 10, 12, 14, 16, 18]
odd_squares = [x**2 for x in range(10) if x % 2 == 1]  # [1, 9, 25, 49, 81]

# String operations
word = "Python"
upper_letters = [char.upper() for char in word]  # ['P', 'Y', 'T', 'H', 'O', 'N']

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

# Filtering and transforming
words = ["hello", "world", "python", "programming"]
long_words = [word.upper() for word in words if len(word) > 5]
# ['PYTHON', 'PROGRAMMING']

13. Tuples in Python

[image:2]

Tuples^13:

  • Definition: Ordered, immutable sequences
  • Creation: Parentheses () or comma separation
  • Usage: Fixed collections, coordinates, database records

Tuple Operations:

# Creating tuples
coordinates = (10.0, 20.0)
colors = ("red", "green", "blue")
single_item = (42,)            # Note the comma for single item
no_parentheses = 1, 2, 3       # Also creates tuple

# Accessing elements
print(coordinates[^0])          # 10.0
print(colors[-1])             # "blue"

# Tuple unpacking
x, y = coordinates
print(f"X: {x}, Y: {y}")

# Multiple assignment
a, b, c = colors
print(a, b, c)                # red green blue

# Tuple methods
numbers = (1, 2, 3, 2, 2, 4)
print(numbers.count(2))       # 3 (occurrences of 2)
print(numbers.index(3))       # 2 (index of first 3)

# Tuples as dictionary keys
locations = {
    (0, 0): "origin",
    (1, 1): "northeast",
    (-1, -1): "southwest"
}

# Named tuples (from collections module)
from collections import namedtuple
Point = namedtuple('Point', ['x', 'y'])
p = Point(3, 4)
print(p.x, p.y)              # 3 4

14. Dictionaries in Python

[image:2]

Dictionaries^13:

  • Definition: Key-value pairs for fast lookups
  • Creation: Curly braces {key: value}
  • Features: Mutable, unordered (Python 3.7+ maintains insertion order)

Dictionary Operations:

# Creating dictionaries
student = {"name": "Alice", "age": 23, "major": "Computer Science"}
empty_dict = {}
from_keys = dict.fromkeys(['a', 'b', 'c'], 0)  # {'a': 0, 'b': 0, 'c': 0}

# Accessing values
print(student["name"])             # "Alice"
print(student.get("grade", "N/A")) # "N/A" (default if key not found)

# Modifying dictionaries
student["age"] = 24                # Update existing key
student["grade"] = "A"             # Add new key-value pair
del student["major"]               # Delete key-value pair
removed = student.pop("grade")     # Remove and return value

# Dictionary methods
print(student.keys())              # dict_keys(['name', 'age'])
print(student.values())            # dict_values(['Alice', 24])
print(student.items())             # dict_items([('name', 'Alice'), ('age', 24)])

# Iterating through dictionaries
for key in student:
    print(f"{key}: {student[key]}")

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

# Dictionary comprehension
squares = {x: x**2 for x in range(5)}  # {0: 0, 1: 1, 2: 4, 3: 9, 4: 16}
even_squares = {x: x**2 for x in range(10) if x % 2 == 0}

# Nested dictionaries
students = {
    "student1": {"name": "John", "grade": 85},
    "student2": {"name": "Jane", "grade": 92}
}
print(students["student1"]["name"])    # "John"

15. Real World Use Cases of List

Data Processing:

# Processing sales data
sales = [1200, 1500, 980, 2100, 1750]
total_sales = sum(sales)
average_sales = total_sales / len(sales)
top_sales = max(sales)

# Finding above-average sales
above_average = [sale for sale in sales if sale > average_sales]

Inventory Management:

# Product inventory
inventory = [
    {"name": "laptop", "quantity": 50, "price": 999.99},
    {"name": "mouse", "quantity": 200, "price": 25.50},
    {"name": "keyboard", "quantity": 75, "price": 79.99}
]

# Low stock items
low_stock = [item for item in inventory if item["quantity"] < 100]

# Total inventory value
total_value = sum(item["quantity"] * item["price"] for item in inventory)

Student Grade Management:

# Student grades
grades = [85, 92, 78, 96, 88, 73, 91]

# Statistical analysis
average_grade = sum(grades) / len(grades)
passing_grades = [grade for grade in grades if grade >= 70]
grade_distribution = {
    'A': len([g for g in grades if g >= 90]),
    'B': len([g for g in grades if 80 <= g < 90]),
    'C': len([g for g in grades if 70 <= g < 80]),
    'F': len([g for g in grades if g < 70])
}

Section 5: Functions in Python

16. Getting Started With Functions

Function Definition:

  • Purpose: Reusable blocks of code that perform specific tasks
  • Benefits: Code reusability, modularity, easier maintenance
  • Syntax: def function_name(parameters):

Basic Function Structure:

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

greet()  # Call the function

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

greet_person("Alice")  # Hello, Alice!

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

sum_result = add_numbers(5, 3)  # Returns 8

# Function with default parameters
def greet_with_title(name, title="Mr./Ms."):
    return f"Hello, {title} {name}!"

print(greet_with_title("Smith"))         # Hello, Mr./Ms. Smith!
print(greet_with_title("Johnson", "Dr.")) # Hello, Dr. Johnson!

17. More Coding Examples With Functions

Functions with Multiple Parameters:

# Function with multiple parameters and return
def calculate_rectangle_area(length, width):
    """Calculate the area of a rectangle."""
    area = length * width
    return area

# Function with variable arguments (*args)
def sum_all(*numbers):
    """Sum all provided numbers."""
    total = 0
    for number in numbers:
        total += number
    return total

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

# Function with keyword arguments (**kwargs)
def create_profile(name, **details):
    """Create a user profile with flexible attributes."""
    profile = {"name": name}
    for key, value in details.items():
        profile[key] = value
    return profile

user = create_profile("Alice", age=25, city="New York", job="Engineer")
print(user)  # {'name': 'Alice', 'age': 25, 'city': 'New York', 'job': 'Engineer'}

# Function returning multiple values
def get_name_parts(full_name):
    """Split full name into first and last name."""
    parts = full_name.split()
    first_name = parts[^0]
    last_name = parts[-1] if len(parts) > 1 else ""
    return first_name, last_name

first, last = get_name_parts("John Doe")
print(f"First: {first}, Last: {last}")

Practical Function Examples:

# Temperature conversion
def celsius_to_fahrenheit(celsius):
    """Convert Celsius to Fahrenheit."""
    fahrenheit = (celsius * 9/5) + 32
    return fahrenheit

def fahrenheit_to_celsius(fahrenheit):
    """Convert Fahrenheit to Celsius."""
    celsius = (fahrenheit - 32) * 5/9
    return celsius

# Validation function
def is_valid_email(email):
    """Basic email validation."""
    return "@" in email and "." in email.split("@")[-1]

# Data processing function
def process_scores(scores):
    """Process a list of scores and return statistics."""
    if not scores:
        return None

    stats = {
        "count": len(scores),
        "average": sum(scores) / len(scores),
        "highest": max(scores),
        "lowest": min(scores),
        "passing": len([s for s in scores if s >= 60])
    }
    return stats

test_scores = [85, 92, 78, 96, 88, 73, 91]
results = process_scores(test_scores)
print(results)

18. Lambda Function in Python

Lambda Functions:

  • Definition: Anonymous functions defined with lambda keyword
  • Syntax: lambda arguments: expression
  • Usage: Short, simple functions for temporary use
  • Limitations: Single expression only, no statements

Lambda Examples:

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

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

# Lambda for string operations
full_name = lambda first, last: f"{first} {last}"
print(full_name("John", "Doe"))  # John Doe

# Lambda with conditional expression
max_val = lambda a, b: a if a > b else b
print(max_val(10, 5))  # 10

# Using lambda in sorting
students = [("Alice", 85), ("Bob", 92), ("Charlie", 78)]
students.sort(key=lambda student: student[^1])  # Sort by grade
print(students)  # [('Charlie', 78), ('Alice', 85), ('Bob', 92)]

19. Map Function in Python

Map Function^15:

  • Purpose: Apply a function to every item in an iterable
  • Syntax: map(function, iterable)
  • Returns: Map object (iterator)
  • Usage: Transform data without explicit loops

Map Examples:

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

# Map with built-in functions
strings = ["1", "2", "3", "4", "5"]
integers = list(map(int, strings))
print(integers)  # [1, 2, 3, 4, 5]

# Map with custom function
def celsius_to_fahrenheit(celsius):
    return (celsius * 9/5) + 32

celsius_temps = [0, 20, 30, 40]
fahrenheit_temps = list(map(celsius_to_fahrenheit, celsius_temps))
print(fahrenheit_temps)  # [32.0, 68.0, 86.0, 104.0]

# Map with multiple iterables
numbers1 = [1, 2, 3]
numbers2 = [4, 5, 6]
products = list(map(lambda x, y: x * y, numbers1, numbers2))
print(products)  # [4, 10, 18]

# Map with string operations
words = ["hello", "world", "python"]
capitalized = list(map(str.upper, words))
print(capitalized)  # ['HELLO', 'WORLD', 'PYTHON']

20. Filter Functions in Python

Filter Function^15:

  • Purpose: Filter elements from iterable based on condition
  • Syntax: filter(function, iterable)
  • Returns: Filter object (iterator)
  • Function: Should return True/False for each element

Filter Examples:

# Basic filter usage
numbers = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
even_numbers = list(filter(lambda x: x % 2 == 0, numbers))
print(even_numbers)  # [2, 4, 6, 8, 10]

# Filter with custom function
def is_positive(n):
    return n > 0

mixed_numbers = [-3, -1, 0, 2, 5, -8, 7]
positive_numbers = list(filter(is_positive, mixed_numbers))
print(positive_numbers)  # [2, 5, 7]

# Filter strings
words = ["apple", "banana", "cherry", "date", "elderberry"]
long_words = list(filter(lambda word: len(word) > 5, words))
print(long_words)  # ['banana', 'cherry', 'elderberry']

# Filter with None (removes falsy values)
mixed_data = [1, 0, "hello", "", None, "world", False, True]
truthy_values = list(filter(None, mixed_data))
print(truthy_values)  # [1, 'hello', 'world', True]

# Complex filtering
students = [
    {"name": "Alice", "grade": 85, "age": 20},
    {"name": "Bob", "grade": 92, "age": 19},
    {"name": "Charlie", "grade": 78, "age": 21},
    {"name": "Diana", "grade": 95, "age": 20}
]

high_achievers = list(filter(lambda s: s["grade"] >= 90, students))
print([s["name"] for s in high_achievers])  # ['Bob', 'Diana']

Section 6: Importing, Creating Modules and Packages

21. Import Modules and Packages in Python

[image:2]

Module Basics^16:

  • Definition: A file containing Python code (functions, classes, variables)
  • Purpose: Code reusability and organization
  • File Extension: .py

Import Methods:

# Standard import
import math
print(math.sqrt(16))  # 4.0

# Import with alias
import numpy as np
array = np.array([1, 2, 3])

# Import specific functions
from math import sqrt, pi
print(sqrt(25))  # 5.0
print(pi)        # 3.141592653589793

# Import all (not recommended)
from math import *

# Import from subdirectory
from mypackage import mymodule
from mypackage.subpackage import utilities

Creating Custom Modules^17:

# mymodule.py
def greet(name):
    return f"Hello, {name}!"

def add(a, b):
    return a + b

PI = 3.14159

# Using the module
# main.py
import mymodule

print(mymodule.greet("World"))  # Hello, World!
print(mymodule.add(5, 3))       # 8
print(mymodule.PI)              # 3.14159

22. Standard Libraries Overview in Python

[image:2]

Essential Standard Libraries^18:

File and System Operations:

  • os: Operating system interface, file paths, environment variables
  • sys: System-specific parameters and functions
  • pathlib: Object-oriented path handling
  • shutil: High-level file operations (copy, move, delete)

Data Processing:

  • json: JSON encoder and decoder
  • csv: CSV file reading and writing
  • sqlite3: SQLite database interface
  • pickle: Python object serialization

Date and Time:

  • datetime: Date and time manipulation
  • time: Time-related functions
  • calendar: Calendar-related functions

Examples:

# os module
import os
print(os.getcwd())              # Current working directory
print(os.listdir('.'))          # List directory contents
os.makedirs('new_folder', exist_ok=True)

# datetime module
from datetime import datetime, date, timedelta
now = datetime.now()
today = date.today()
tomorrow = today + timedelta(days=1)
print(f"Today: {today}, Tomorrow: {tomorrow}")

# json module
import json
data = {"name": "Alice", "age": 25}
json_string = json.dumps(data)
parsed_data = json.loads(json_string)

# random module
import random
print(random.randint(1, 10))    # Random integer between 1 and 10
print(random.choice(['a', 'b', 'c']))  # Random choice from list

# math module
import math
print(math.factorial(5))        # 120
print(math.gcd(12, 18))        # 6
print(math.degrees(math.pi))    # 180.0

Advanced Libraries:

# collections module
from collections import Counter, defaultdict, namedtuple
count = Counter("hello world")
print(count)  # Counter({'l': 3, 'o': 2, 'h': 1, 'e': 1, ' ': 1, 'w': 1, 'r': 1, 'd': 1})

# itertools module
import itertools
numbers = [1, 2, 3]
permutations = list(itertools.permutations(numbers))
print(permutations)  # [(1, 2, 3), (1, 3, 2), (2, 1, 3), (2, 3, 1), (3, 1, 2), (3, 2, 1)]

# functools module
from functools import reduce
numbers = [1, 2, 3, 4, 5]
product = reduce(lambda x, y: x * y, numbers)
print(product)  # 120

Section 7: File Handling in Python

23. File Operations With Python

[image:3]

File Opening Modes^19:

  • 'r': Read mode (default)
  • 'w': Write mode (overwrites existing file)
  • 'a': Append mode
  • 'x': Exclusive creation (fails if file exists)
  • 'b': Binary mode (e.g., 'rb', 'wb')
  • 't': Text mode (default)

Basic File Operations:

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

# Reading entire file
with open('example.txt', 'r') as file:
    content = file.read()
    print(content)

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

# Reading specific number of characters
with open('example.txt', 'r') as file:
    first_10_chars = file.read(10)
    print(first_10_chars)

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

File Handling Best Practices:

# Using context manager (with statement) - recommended
with open('data.txt', 'r') as file:
    data = file.read()
# File automatically closed after with block

# Manual file handling (not recommended)
file = open('data.txt', 'r')
data = file.read()
file.close()  # Must remember to close

# Error handling with files
try:
    with open('nonexistent.txt', 'r') as file:
        content = file.read()
except FileNotFoundError:
    print("File not found!")
except PermissionError:
    print("Permission denied!")

Working with CSV Files:

import csv

# Writing CSV
data = [
    ['Name', 'Age', 'City'],
    ['Alice', 25, 'New York'],
    ['Bob', 30, 'London'],
    ['Charlie', 35, 'Paris']
]

with open('people.csv', 'w', newline='') as file:
    writer = csv.writer(file)
    writer.writerows(data)

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

# Working with CSV as dictionaries
with open('people.csv', 'r') as file:
    reader = csv.DictReader(file)
    for row in reader:
        print(f"Name: {row['Name']}, Age: {row['Age']}")

24. Working with File Paths

[image:3]

Path Handling^20:

  • os.path: Traditional path manipulation
  • pathlib: Modern, object-oriented approach (Python 3.4+)
  • Cross-platform: Handles Windows/Unix differences automatically

Using pathlib (Recommended):

from pathlib import Path

# Creating paths
current_dir = Path.cwd()              # Current working directory
home_dir = Path.home()                # User home directory
file_path = Path('documents/file.txt')

# Path operations
print(file_path.name)         # 'file.txt'
print(file_path.stem)         # 'file'
print(file_path.suffix)       # '.txt'
print(file_path.parent)       # 'documents'

# Joining paths
project_path = Path('projects') / 'my_project' / 'src' / 'main.py'
print(project_path)

# Checking path properties
if file_path.exists():
    print("File exists")
if file_path.is_file():
    print("It's a file")
if file_path.is_dir():
    print("It's a directory")

# Creating directories
new_dir = Path('new_folder')
new_dir.mkdir(exist_ok=True)  # exist_ok=True prevents error if exists

# Listing directory contents
for item in Path('.').iterdir():
    if item.is_file():
        print(f"File: {item.name}")
    else:
        print(f"Directory: {item.name}")

Using os.path (Traditional):

import os

# Path operations
current_dir = os.getcwd()
file_path = os.path.join('documents', 'file.txt')

# Path information
print(os.path.basename(file_path))    # 'file.txt'
print(os.path.dirname(file_path))     # 'documents'
print(os.path.splitext(file_path))    # ('documents/file', '.txt')

# Checking paths
if os.path.exists(file_path):
    print("Path exists")
if os.path.isfile(file_path):
    print("It's a file")
if os.path.isdir(file_path):
    print("It's a directory")

# Creating directories
os.makedirs('new_folder', exist_ok=True)

# Listing directory
for item in os.listdir('.'):
    full_path = os.path.join('.', item)
    if os.path.isfile(full_path):
        print(f"File: {item}")
    else:
        print(f"Directory: {item}")

Section 8: Exception Handling

25. Exception Handling With try except else and finally blocks

[image:3]

Exception Handling Structure^21:

  • try: Test block of code for errors
  • except: Handle specific errors
  • else: Execute when no errors occur
  • finally: Always execute (cleanup code)

Basic Exception Handling:

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

# Multiple exception types
try:
    num = int(input("Enter a number: "))
    result = 10 / num
    print(f"Result: {result}")
except ValueError:
    print("Invalid input! Please enter a number.")
except ZeroDivisionError:
    print("Cannot divide by zero!")

# Generic exception handling
try:
    # Some risky operation
    file = open('nonexistent.txt', 'r')
except Exception as e:
    print(f"An error occurred: {e}")

Complete Exception Handling:

def divide_numbers(a, b):
    try:
        result = a / b
    except ZeroDivisionError:
        print("Error: Division by zero!")
        return None
    except TypeError:
        print("Error: Invalid data types!")
        return None
    else:
        print("Division successful!")
        return result
    finally:
        print("Division operation completed.")

# Testing the function
print(divide_numbers(10, 2))    # Successful division
print(divide_numbers(10, 0))    # Division by zero
print(divide_numbers(10, "2"))  # Type error

File Handling with Exception Handling:

def read_file_safely(filename):
    try:
        with open(filename, 'r') as file:
            content = file.read()
            return content
    except FileNotFoundError:
        print(f"Error: File '{filename}' not found.")
        return None
    except PermissionError:
        print(f"Error: Permission denied to access '{filename}'.")
        return None
    except Exception as e:
        print(f"Unexpected error: {e}")
        return None
    else:
        print("File read successfully!")
    finally:
        print("File operation completed.")

# Usage
content = read_file_safely('example.txt')
if content:
    print(content)

Custom Exception Handling:

# Custom exception class
class InvalidAgeError(Exception):
    """Custom exception for invalid age values."""
    pass

def validate_age(age):
    try:
        age = int(age)
        if age < 0:
            raise InvalidAgeError("Age cannot be negative!")
        elif age > 150:
            raise InvalidAgeError("Age seems unrealistic!")
        return age
    except ValueError:
        raise InvalidAgeError("Age must be a number!")

# Using custom exception
try:
    user_age = validate_age("25")
    print(f"Valid age: {user_age}")

    invalid_age = validate_age("-5")
except InvalidAgeError as e:
    print(f"Age validation error: {e}")

Section 9: OOPS Classes and Objects

26. Classes and Objects in Python

[image:3]

Object-Oriented Programming Concepts:

  • Class: Blueprint for creating objects
  • Object: Instance of a class
  • Attributes: Variables that belong to a class/object
  • Methods: Functions that belong to a class

Basic Class Definition:

class Person:
    # Class attribute (shared by all instances)
    species = "Homo sapiens"

    def __init__(self, name, age):
        # Instance attributes (unique to each object)
        self.name = name
        self.age = age

    def introduce(self):
        return f"Hi, I'm {self.name} and I'm {self.age} years old."

    def have_birthday(self):
        self.age += 1
        return f"Happy birthday! {self.name} is now {self.age}."

# Creating objects (instances)
person1 = Person("Alice", 25)
person2 = Person("Bob", 30)

# Accessing attributes and methods
print(person1.name)           # Alice
print(person1.introduce())    # Hi, I'm Alice and I'm 25 years old.
print(person1.have_birthday()) # Happy birthday! Alice is now 26.

# Class attribute access
print(person1.species)        # Homo sapiens
print(Person.species)         # Homo sapiens

More Complex Class Example:

class BankAccount:
    # Class attribute
    bank_name = "Python Bank"

    def __init__(self, account_holder, initial_balance=0):
        self.account_holder = account_holder
        self.balance = initial_balance
        self.transaction_history = []

    def deposit(self, amount):
        if amount > 0:
            self.balance += amount
            self.transaction_history.append(f"Deposited ${amount}")
            return f"${amount} deposited. New balance: ${self.balance}"
        else:
            return "Invalid deposit amount."

    def withdraw(self, amount):
        if amount > 0 and amount <= self.balance:
            self.balance -= amount
            self.transaction_history.append(f"Withdrew ${amount}")
            return f"${amount} withdrawn. New balance: ${self.balance}"
        else:
            return "Invalid withdrawal amount or insufficient funds."

    def get_balance(self):
        return f"Current balance: ${self.balance}"

    def get_transaction_history(self):
        return self.transaction_history

# Using the class
account = BankAccount("John Doe", 1000)
print(account.deposit(500))         # $500 deposited. New balance: $1500
print(account.withdraw(200))        # $200 withdrawn. New balance: $1300
print(account.get_balance())        # Current balance: $1300
print(account.get_transaction_history())  # ['Deposited $500', 'Withdrew $200']

27. Single and Multiple Inheritance

[image:3]

Single Inheritance^22:

  • Definition: Child class inherits from one parent class
  • Syntax: class Child(Parent):
  • Benefits: Code reuse, hierarchical organization

Single Inheritance Example:

# Parent class
class Animal:
    def __init__(self, name, species):
        self.name = name
        self.species = species

    def make_sound(self):
        return f"{self.name} makes a sound."

    def info(self):
        return f"{self.name} is a {self.species}."

# Child class inheriting from Animal
class Dog(Animal):
    def __init__(self, name, breed):
        super().__init__(name, "Dog")  # Call parent constructor
        self.breed = breed

    def make_sound(self):  # Method overriding
        return f"{self.name} barks: Woof!"

    def fetch(self):  # New method specific to Dog
        return f"{self.name} fetches the ball!"

# Using inheritance
my_dog = Dog("Buddy", "Golden Retriever")
print(my_dog.info())        # Buddy is a Dog.
print(my_dog.make_sound())  # Buddy barks: Woof!
print(my_dog.fetch())       # Buddy fetches the ball!

Multiple Inheritance:

  • Definition: Child class inherits from multiple parent classes
  • Syntax: class Child(Parent1, Parent2):
  • Method Resolution Order (MRO): Determines which method is called

Multiple Inheritance Example:

class Flyable:
    def fly(self):
        return "Flying through the air!"

class Swimmable:
    def swim(self):
        return "Swimming in water!"

class Duck(Animal, Flyable, Swimmable):
    def __init__(self, name):
        super().__init__(name, "Duck")

    def make_sound(self):
        return f"{self.name} quacks: Quack!"

# Using multiple inheritance
duck = Duck("Donald")
print(duck.info())        # Donald is a Duck.
print(duck.make_sound())  # Donald quacks: Quack!
print(duck.fly())         # Flying through the air!
print(duck.swim())        # Swimming in water!

# Check Method Resolution Order
print(Duck.__mro__)       # Shows the order of method resolution

28. Polymorphism in OOPS

Polymorphism^23:

  • Definition: Same interface, different implementations
  • Types: Method overriding, duck typing
  • Benefit: Code flexibility and extensibility

Polymorphism Examples:

# Base class
class Shape:
    def area(self):
        raise NotImplementedError("Subclass must implement area method")

    def perimeter(self):
        raise NotImplementedError("Subclass must implement perimeter method")

# Different shapes with same interface
class Rectangle(Shape):
    def __init__(self, width, height):
        self.width = width
        self.height = height

    def area(self):
        return self.width * self.height

    def perimeter(self):
        return 2 * (self.width + self.height)

class Circle(Shape):
    def __init__(self, radius):
        self.radius = radius

    def area(self):
        return 3.14159 * self.radius ** 2

    def perimeter(self):
        return 2 * 3.14159 * self.radius

class Triangle(Shape):
    def __init__(self, base, height, side1, side2, side3):
        self.base = base
        self.height = height
        self.side1 = side1
        self.side2 = side2
        self.side3 = side3

    def area(self):
        return 0.5 * self.base * self.height

    def perimeter(self):
        return self.side1 + self.side2 + self.side3

# Polymorphism in action
def print_shape_info(shape):
    """Function that works with any shape object"""
    print(f"Area: {shape.area():.2f}")
    print(f"Perimeter: {shape.perimeter():.2f}")
    print("-" * 20)

# Using polymorphism
shapes = [
    Rectangle(5, 3),
    Circle(4),
    Triangle(6, 4, 5, 5, 6)
]

for shape in shapes:
    print_shape_info(shape)

29. Encapsulation in OOPS

Encapsulation^23:

  • Definition: Bundling data and methods, controlling access
  • Private attributes: Single underscore _ (convention), double underscore __ (name mangling)
  • Property decorators: @property, @setter, @deleter

Encapsulation Examples:

class Student:
    def __init__(self, name, age):
        self._name = name        # Protected attribute (convention)
        self.__age = age         # Private attribute (name mangling)
        self.__grades = []       # Private list

    @property
    def name(self):
        """Getter for name"""
        return self._name

    @name.setter
    def name(self, value):
        """Setter for name with validation"""
        if isinstance(value, str) and len(value) > 0:
            self._name = value
        else:
            raise ValueError("Name must be a non-empty string")

    @property
    def age(self):
        """Getter for age"""
        return self.__age

    @age.setter
    def age(self, value):
        """Setter for age with validation"""
        if isinstance(value, int) and 0 <= value <= 150:
            self.__age = value
        else:
            raise ValueError("Age must be between 0 and 150")

    def add_grade(self, grade):
        """Public method to add grade"""
        if 0 <= grade <= 100:
            self.__grades.append(grade)
        else:
            raise ValueError("Grade must be between 0 and 100")

    def get_average_grade(self):
        """Public method to get average grade"""
        if self.__grades:
            return sum(self.__grades) / len(self.__grades)
        return 0

    def get_grades(self):
        """Public method to get copy of grades"""
        return self.__grades.copy()  # Return copy to prevent direct modification

# Using encapsulation
student = Student("Alice", 20)

# Using property
print(student.name)         # Alice
student.name = "Alice Smith"
print(student.name)         # Alice Smith

# Accessing age through property
print(student.age)          # 20
student.age = 21
print(student.age)          # 21

# Adding grades
student.add_grade(85)
student.add_grade(92)
student.add_grade(78)

print(f"Average grade: {student.get_average_grade():.2f}")  # Average grade: 85.00
print(f"Grades: {student.get_grades()}")  # Grades: [85, 92, 78]

# Attempting direct access to private attribute
# print(student.__age)      # This would raise AttributeError
# But can access via name mangling (not recommended):
# print(student._Student__age)  # 21

30. Abstraction in OOPS

Abstraction^23:

  • Definition: Hide implementation details, show only essential features
  • Abstract Base Classes: Use abc module
  • Abstract methods: Must be implemented by subclasses

Abstraction Examples:

from abc import ABC, abstractmethod

class Vehicle(ABC):
    """Abstract base class for vehicles"""

    def __init__(self, brand, model):
        self.brand = brand
        self.model = model

    @abstractmethod
    def start_engine(self):
        """Abstract method - must be implemented by subclasses"""
        pass

    @abstractmethod
    def stop_engine(self):
        """Abstract method - must be implemented by subclasses"""
        pass

    def get_info(self):
        """Concrete method available to all subclasses"""
        return f"{self.brand} {self.model}"

class Car(Vehicle):
    def __init__(self, brand, model, num_doors):
        super().__init__(brand, model)
        self.num_doors = num_doors

    def start_engine(self):
        return f"{self.get_info()} car engine started with ignition key."

    def stop_engine(self):
        return f"{self.get_info()} car engine stopped."

    def open_doors(self):
        return f"Opening {self.num_doors} doors."

class Motorcycle(Vehicle):
    def __init__(self, brand, model, engine_size):
        super().__init__(brand, model)
        self.engine_size = engine_size

    def start_engine(self):
        return f"{self.get_info()} motorcycle engine started with kick/button."

    def stop_engine(self):
        return f"{self.get_info()} motorcycle engine stopped."

    def wheelie(self):
        return f"{self.get_info()} doing a wheelie!"

# Using abstraction
# vehicle = Vehicle("Generic", "Model")  # This would raise TypeError

car = Car("Toyota", "Camry", 4)
motorcycle = Motorcycle("Honda", "CBR", "600cc")

print(car.start_engine())           # Toyota Camry car engine started with ignition key.
print(car.open_doors())             # Opening 4 doors.

print(motorcycle.start_engine())    # Honda CBR motorcycle engine started with kick/button.
print(motorcycle.wheelie())         # Honda CBR doing a wheelie!

# Polymorphism with abstract classes
vehicles = [car, motorcycle]
for vehicle in vehicles:
    print(vehicle.start_engine())
    print(vehicle.stop_engine())

31. Magic Methods in Python

Magic Methods (Dunder Methods)^24:

  • Definition: Special methods with double underscores
  • Purpose: Define how objects behave with built-in operations
  • Automatic invocation: Called by Python interpreter

Common Magic Methods:

class Book:
    def __init__(self, title, author, pages):
        self.title = title
        self.author = author
        self.pages = pages

    def __str__(self):
        """String representation for end users"""
        return f"{self.title} by {self.author}"

    def __repr__(self):
        """String representation for developers"""
        return f"Book('{self.title}', '{self.author}', {self.pages})"

    def __len__(self):
        """Return length (number of pages)"""
        return self.pages

    def __eq__(self, other):
        """Define equality comparison"""
        if isinstance(other, Book):
            return (self.title == other.title and 
                   self.author == other.author)
        return False

    def __lt__(self, other):
        """Define less than comparison (by pages)"""
        if isinstance(other, Book):
            return self.pages < other.pages
        return NotImplemented

    def __add__(self, other):
        """Define addition (combine pages)"""
        if isinstance(other, Book):
            return self.pages + other.pages
        return NotImplemented

# Using magic methods
book1 = Book("1984", "George Orwell", 328)
book2 = Book("Animal Farm", "George Orwell", 112)
book3 = Book("1984", "George Orwell", 328)

print(str(book1))       # 1984 by George Orwell (__str__)
print(repr(book1))      # Book('1984', 'George Orwell', 328) (__repr__)
print(len(book1))       # 328 (__len__)
print(book1 == book3)   # True (__eq__)
print(book1 < book2)    # False (__lt__)
print(book1 + book2)    # 440 (__add__)

32. Operator Overloading in Python

Operator Overloading^26:

  • Definition: Giving additional meanings to operators for custom classes
  • Magic Methods: Use dunder methods to define operator behavior
  • Benefits: Natural, intuitive operations on custom objects

Comprehensive Operator Overloading Example:

class Vector:
    def __init__(self, x, y):
        self.x = x
        self.y = y

    def __str__(self):
        return f"Vector({self.x}, {self.y})"

    def __repr__(self):
        return f"Vector({self.x}, {self.y})"

    # Arithmetic operators
    def __add__(self, other):
        """Addition: v1 + v2"""
        if isinstance(other, Vector):
            return Vector(self.x + other.x, self.y + other.y)
        return NotImplemented

    def __sub__(self, other):
        """Subtraction: v1 - v2"""
        if isinstance(other, Vector):
            return Vector(self.x - other.x, self.y - other.y)
        return NotImplemented

    def __mul__(self, scalar):
        """Scalar multiplication: v * scalar"""
        if isinstance(scalar, (int, float)):
            return Vector(self.x * scalar, self.y * scalar)
        return NotImplemented

    def __rmul__(self, scalar):
        """Right scalar multiplication: scalar * v"""
        return self.__mul__(scalar)

    def __truediv__(self, scalar):
        """Division: v / scalar"""
        if isinstance(scalar, (int, float)) and scalar != 0:
            return Vector(self.x / scalar, self.y / scalar)
        return NotImplemented

    # Comparison operators
    def __eq__(self, other):
        """Equality: v1 == v2"""
        if isinstance(other, Vector):
            return self.x == other.x and self.y == other.y
        return False

    def __lt__(self, other):
        """Less than: v1 < v2 (by magnitude)"""
        if isinstance(other, Vector):
            return self.magnitude() < other.magnitude()
        return NotImplemented

    # Unary operators
    def __neg__(self):
        """Negation: -v"""
        return Vector(-self.x, -self.y)

    def __abs__(self):
        """Absolute value: abs(v) - magnitude"""
        return self.magnitude()

    # Helper method
    def magnitude(self):
        """Calculate vector magnitude"""
        return (self.x ** 2 + self.y ** 2) ** 0.5

# Using operator overloading
v1 = Vector(3, 4)
v2 = Vector(1, 2)

print(f"v1: {v1}")              # v1: Vector(3, 4)
print(f"v2: {v2}")              # v2: Vector(1, 2)

print(f"v1 + v2: {v1 + v2}")    # v1 + v2: Vector(4, 6)
print(f"v1 - v2: {v1 - v2}")    # v1 - v2: Vector(2, 2)
print(f"v1 * 2: {v1 * 2}")      # v1 * 2: Vector(6, 8)
print(f"3 * v2: {3 * v2}")      # 3 * v2: Vector(3, 6)
print(f"v1 / 2: {v1 / 2}")      # v1 / 2: Vector(1.5, 2.0)

print(f"v1 == v2: {v1 == v2}")  # v1 == v2: False
print(f"v1 < v2: {v1 < v2}")    # v1 < v2: False
print(f"-v1: {-v1}")            # -v1: Vector(-3, -4)
print(f"abs(v1): {abs(v1)}")    # abs(v1): 5.0

This comprehensive revision guide covers all the Python topics shown in your images, providing detailed explanations, practical examples, and best practices for each concept. Each section includes crisp, bullet-pointed notes with working code examples that demonstrate the usage of each Python feature.

⁂

Python-1

Python Revision Notes - Comprehensive Study Guide Section 1: Python Environment Setup 4. Different Ways of Creating Python Environment [...