0% found this document useful (0 votes)
4 views75 pages

Complete Python Programming Guide

The document is a comprehensive guide to Python programming, covering topics from fundamentals to advanced concepts. It includes sections on object-oriented programming, data structures, string manipulation, regular expressions, error handling, type hints, and concurrency. Each section provides practical examples and explanations to facilitate learning for beginners and advanced users alike.
Copyright
© All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
4 views75 pages

Complete Python Programming Guide

The document is a comprehensive guide to Python programming, covering topics from fundamentals to advanced concepts. It includes sections on object-oriented programming, data structures, string manipulation, regular expressions, error handling, type hints, and concurrency. Each section provides practical examples and explanations to facilitate learning for beginners and advanced users alike.
Copyright
© All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd

Complete Python Programming Guide: Beginner to Advanced

Table of Contents

1. Python Fundamentals

2. Object-Oriented Programming

3. Data Structures & Collections

4. String Processing & Text Manipulation

5. Regular Expressions

6. Error Handling & Control Flow

7. Type Hints & Modern Python

8. Concurrency & Threading

9. Performance Optimization

10. Design Patterns & Interfaces

11. Email Processing & Automation

12. Advanced Projects

1. Python Fundamentals

1.1 Basic Syntax & Variables

# Variables and basic data types

name = "Alice" # String

age = 25 # Integer

height = 5.6 # Float

is_student = True # Boolean

# Basic operations

total = age + 10

greeting = f"Hello, {name}!" # f-string formatting

print(greeting) # Output: Hello, Alice!

1.2 Control Structures


# If statements

if age >= 18:

print("Adult")

elif age >= 13:

print("Teenager")

else:

print("Child")

# Loops

# For loop

for i in range(5):

print(f"Count: {i}")

# While loop

count = 0

while count < 3:

print(f"While count: {count}")

count += 1

# List comprehension (advanced for loop)

squares = [x**2 for x in range(5)] # [0, 1, 4, 9, 16]

1.3 Functions

# Basic function

def greet(name):

return f"Hello, {name}!"

# Function with default parameters

def greet_with_title(name, title="Mr."):

return f"Hello, {title} {name}!"


# Function with multiple return values

def calculate(a, b):

return a + b, a - b, a * b

sum_result, diff_result, mult_result = calculate(10, 5)

# Lambda functions (anonymous functions)

square = lambda x: x**2

print(square(5)) # Output: 25

2. Object-Oriented Programming

2.1 Classes and Objects (Beginner)

class Person:

# Class attribute (shared by all instances)

species = "Homo sapiens"

# Constructor method

def __init__(self, name, age):

# Instance attributes

[Link] = name

[Link] = age

# Instance method

def introduce(self):

return f"Hi, I'm {[Link]} and I'm {[Link]} years old."

# String representation

def __str__(self):
return f"Person(name='{[Link]}', age={[Link]})"

# Creating objects

person1 = Person("Alice", 25)

person2 = Person("Bob", 30)

print([Link]()) # Hi, I'm Alice and I'm 25 years old.

print(person1) # Person(name='Alice', age=25)

2.2 Inheritance (Intermediate)

class Employee(Person): # Employee inherits from Person

def __init__(self, name, age, employee_id, salary):

super().__init__(name, age) # Call parent constructor

self.employee_id = employee_id

[Link] = salary

# Method overriding

def introduce(self):

base_intro = super().introduce()

return f"{base_intro} I work here as employee #{self.employee_id}."

# New method specific to Employee

def get_annual_salary(self):

return [Link] * 12

# Multiple inheritance

class Manager(Employee):

def __init__(self, name, age, employee_id, salary, team_size):

super().__init__(name, age, employee_id, salary)

self.team_size = team_size
def manage_team(self):

return f"Managing a team of {self.team_size} people."

# Usage

manager = Manager("Carol", 35, "M001", 8000, 10)

print([Link]())

print(manager.manage_team())

2.3 Advanced OOP Concepts

from abc import ABC, abstractmethod

# Abstract base class

class Animal(ABC):

def __init__(self, name):

[Link] = name

@abstractmethod

def make_sound(self):

pass # Must be implemented by subclasses

def sleep(self):

return f"{[Link]} is sleeping."

class Dog(Animal):

def make_sound(self):

return f"{[Link]} says Woof!"

class Cat(Animal):

def make_sound(self):
return f"{[Link]} says Meow!"

# Property decorators

class Circle:

def __init__(self, radius):

self._radius = radius

@property

def radius(self):

return self._radius

@[Link]

def radius(self, value):

if value < 0:

raise ValueError("Radius cannot be negative")

self._radius = value

@property

def area(self):

return 3.14159 * self._radius ** 2

# Class methods and static methods

class MathUtils:

@staticmethod

def add(a, b):

return a + b

@classmethod

def from_string(cls, calc_string):


# Factory method

a, operator, b = calc_string.split()

return [Link](int(a), int(b)) if operator == '+' else None

3. Data Structures & Collections

3.1 Built-in Data Structures

# Lists (mutable, ordered)

fruits = ["apple", "banana", "cherry"]

[Link]("date")

[Link](1, "blueberry")

[Link]("banana")

# List slicing

print(fruits[1:3]) # ['blueberry', 'cherry']

print(fruits[:2]) # ['apple', 'blueberry']

print(fruits[-1]) # Last element

# Tuples (immutable, ordered)

coordinates = (10, 20)

x, y = coordinates # Tuple unpacking

# Dictionaries (mutable, key-value pairs)

person = {

"name": "Alice",

"age": 25,

"city": "New York"

# Dictionary methods
print([Link]()) # dict_keys(['name', 'age', 'city'])

print([Link]()) # dict_values(['Alice', 25, 'New York'])

print([Link]()) # dict_items([('name', 'Alice'), ...])

# Sets (mutable, unique elements)

unique_numbers = {1, 2, 3, 2, 1} # {1, 2, 3}

unique_numbers.add(4)

unique_numbers.discard(2)

3.2 Advanced Collections

from collections import defaultdict, Counter, namedtuple, deque

# defaultdict - provides default values

word_count = defaultdict(int)

text = "hello world hello"

for word in [Link]():

word_count[word] += 1

# Counter - counts elements

counter = Counter("hello world")

print(counter) # Counter({'l': 3, 'o': 2, 'h': 1, 'e': 1, ' ': 1, 'w': 1, 'r': 1, 'd': 1})

# namedtuple - creates tuple subclass with named fields

Point = namedtuple('Point', ['x', 'y'])

p = Point(10, 20)

print(p.x, p.y) # 10 20

# deque - double-ended queue (efficient append/pop from both ends)

queue = deque([1, 2, 3])

[Link](0) # [0, 1, 2, 3]
[Link](4) # [0, 1, 2, 3, 4]

4. String Processing & Text Manipulation

4.1 Basic String Operations

text = " Hello, World! "

# Basic methods

print([Link]()) # " hello, world! "

print([Link]()) # " HELLO, WORLD! "

print([Link]()) # "Hello, World!"

print([Link]("World", "Python")) # " Hello, Python! "

# String formatting

name = "Alice"

age = 25

# Old style (avoid)

old_format = "Name: %s, Age: %d" % (name, age)

# New style

new_format = "Name: {}, Age: {}".format(name, age)

# f-strings (preferred in Python 3.6+)

f_string = f"Name: {name}, Age: {age}"

4.2 Advanced String Processing

# String methods for analysis

text = "The quick brown fox jumps over the lazy dog"

# Checking string properties


print([Link]("The")) # True

print([Link]("dog")) # True

print("fox" in text) # True

# Splitting and joining

words = [Link]() # Split by whitespace

print(words) # ['The', 'quick', 'brown', ...]

# Join words back

rejoined = " ".join(words)

# Split with custom delimiter

csv_data = "apple,banana,cherry"

fruits = csv_data.split(",")

# String validation

email = "user@[Link]"

print([Link]("@")) # Should be 1 for valid email

# Multi-line strings

multiline = """

This is a

multi-line

string

""".strip()

5. Regular Expressions

5.1 Basic Pattern Matching

import re
# Basic pattern matching

text = "Hello, my email is john@[Link]"

pattern = r"\w+@\w+\.\w+"

# Search for pattern

match = [Link](pattern, text)

if match:

print(f"Found email: {[Link]()}") # john@[Link]

# Find all matches

emails = "Contact us at info@[Link] or support@[Link]"

all_emails = [Link](r"\w+@\w+\.\w+", emails)

print(all_emails) # ['info@[Link]', 'support@[Link]']

5.2 Advanced Regex Patterns

# Compiled patterns (more efficient for repeated use)

email_pattern = [Link](r"[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}")

phone_pattern = [Link](r"\(?\d{3}\)?[-.\s]?\d{3}[-.\s]?\d{4}")

# Groups and capturing

text = "John Doe, age 30, lives in New York"

pattern = r"(\w+)\s(\w+),\sage\s(\d+),\slives\sin\s(.+)"

match = [Link](pattern, text)

if match:

first_name, last_name, age, city = [Link]()

print(f"Name: {first_name} {last_name}, Age: {age}, City: {city}")

# Named groups (more readable)


pattern = r"(?P<first>\w+)\s(?P<last>\w+),\sage\s(?P<age>\d+)"

match = [Link](pattern, text)

if match:

print([Link]()) # {'first': 'John', 'last': 'Doe', 'age': '30'}

# Lookahead and lookbehind

# Positive lookahead: (?=pattern)

# Negative lookahead: (?!pattern)

# Positive lookbehind: (?<=pattern)

# Negative lookbehind: (?<!pattern)

# Find words that are followed by numbers

pattern = r"\w+(?=\d)"

text = "item1 product2 service"

matches = [Link](pattern, text) # ['item', 'product']

5.3 Regex Flags and Advanced Features

# Common flags

text = """

John SMITH: john@[Link]

Jane DOE: jane@[Link]

"""

# Case insensitive

pattern = [Link](r"john", [Link])

matches = [Link](text) # ['John', 'john']

# Multiline mode

pattern = [Link](r"^Jane", [Link])

matches = [Link](text) # ['Jane']


# Dotall mode (. matches newlines)

pattern = [Link](r"John.*jane", [Link] | [Link])

# Substitution with functions

def capitalize_match(match):

return [Link]().upper()

text = "hello world"

result = [Link](r"\w+", capitalize_match, text) # "HELLO WORLD"

6. Error Handling & Control Flow

6.1 Basic Exception Handling

# Try-except blocks

def divide_numbers(a, b):

try:

result = a / b

return result

except ZeroDivisionError:

print("Error: Cannot divide by zero!")

return None

except TypeError:

print("Error: Invalid input types!")

return None

# Multiple exceptions

def process_data(data):

try:

# Process the data


number = int(data)

result = 100 / number

return result

except (ValueError, TypeError) as e:

print(f"Input error: {e}")

except ZeroDivisionError as e:

print(f"Math error: {e}")

except Exception as e:

print(f"Unexpected error: {e}")

finally:

# Always executes

print("Processing complete")

6.2 Custom Exceptions

# Custom exception classes

class InvalidEmailError(Exception):

"""Raised when an email address is invalid"""

def __init__(self, email, message="Invalid email address"):

[Link] = email

[Link] = message

super().__init__([Link])

class EmailProcessor:

def validate_email(self, email):

if "@" not in email:

raise InvalidEmailError(email, f"Email '{email}' is missing @ symbol")

if "." not in [Link]("@")[1]:

raise InvalidEmailError(email, f"Email '{email}' has invalid domain")


def process_email(self, email):

try:

self.validate_email(email)

print(f"Processing email: {email}")

except InvalidEmailError as e:

print(f"Email validation failed: {[Link]}")

raise # Re-raise the exception

6.3 Context Managers

# Built-in context managers

with open("[Link]", "r") as file:

content = [Link]()

# File is automatically closed after the block

# Custom context manager using class

class DatabaseConnection:

def __enter__(self):

print("Connecting to database...")

return self

def __exit__(self, exc_type, exc_val, exc_tb):

print("Closing database connection...")

if exc_type:

print(f"An error occurred: {exc_val}")

return False # Don't suppress exceptions

# Custom context manager using contextlib

from contextlib import contextmanager

@contextmanager
def timer():

import time

start = [Link]()

try:

yield

finally:

end = [Link]()

print(f"Execution time: {end - start:.2f} seconds")

# Usage

with timer():

# Some time-consuming operation

sum(range(1000000))

7. Type Hints & Modern Python

7.1 Basic Type Hints

from typing import List, Dict, Optional, Union, Tuple

# Basic type hints

def greet(name: str) -> str:

return f"Hello, {name}!"

def calculate_area(length: float, width: float) -> float:

return length * width

# Collection type hints

def process_numbers(numbers: List[int]) -> Dict[str, int]:

return {

"sum": sum(numbers),
"count": len(numbers),

"max": max(numbers) if numbers else 0

# Optional types (can be None)

def find_user(user_id: int) -> Optional[str]:

users = {1: "Alice", 2: "Bob"}

return [Link](user_id)

# Union types (multiple possible types)

def process_id(user_id: Union[int, str]) -> str:

return f"Processing user: {user_id}"

7.2 Advanced Type Hints

from typing import Callable, Generic, TypeVar, Protocol

from dataclasses import dataclass

# Function type hints

def apply_operation(numbers: List[int], operation: Callable[[int], int]) -> List[int]:

return [operation(num) for num in numbers]

# Usage

result = apply_operation([1, 2, 3], lambda x: x * 2)

# Generic types

T = TypeVar('T')

class Stack(Generic[T]):

def __init__(self) -> None:

self._items: List[T] = []
def push(self, item: T) -> None:

self._items.append(item)

def pop(self) -> T:

return self._items.pop()

# Protocols (structural typing)

class Drawable(Protocol):

def draw(self) -> None: ...

class Circle:

def draw(self) -> None:

print("Drawing a circle")

def render_shape(shape: Drawable) -> None:

[Link]()

# Dataclasses

@dataclass

class Person:

name: str

age: int

email: Optional[str] = None

def is_adult(self) -> bool:

return [Link] >= 18

# Usage
person = Person("Alice", 25, "alice@[Link]")

print([Link]) # Alice

print(person.is_adult()) # True

8. Concurrency & Threading

8.1 Threading Basics

import threading

import time

# Basic threading

def worker(name, delay):

print(f"Worker {name} starting")

[Link](delay)

print(f"Worker {name} finished")

# Create and start threads

thread1 = [Link](target=worker, args=("A", 2))

thread2 = [Link](target=worker, args=("B", 1))

[Link]()

[Link]()

# Wait for threads to complete

[Link]()

[Link]()

print("All threads completed")

8.2 Thread Synchronization

import threading
import time

# Thread-safe counter with Lock

class SafeCounter:

def __init__(self):

self._value = 0

self._lock = [Link]()

def increment(self):

with self._lock:

current = self._value

[Link](0.001) # Simulate some processing

self._value = current + 1

@property

def value(self):

with self._lock:

return self._value

# Event synchronization

def waiter(event):

print("Waiter: waiting for event...")

[Link]()

print("Waiter: event received!")

def setter(event):

[Link](2)

print("Setter: setting event")

[Link]()
event = [Link]()

t1 = [Link](target=waiter, args=(event,))

t2 = [Link](target=setter, args=(event,))

[Link]()

[Link]()

8.3 ThreadPoolExecutor

from [Link] import ThreadPoolExecutor, as_completed

import requests

import time

# Example: Concurrent HTTP requests

def fetch_url(url):

try:

response = [Link](url, timeout=5)

return f"{url}: {response.status_code}"

except Exception as e:

return f"{url}: Error - {e}"

urls = [

"[Link]

"[Link]

"[Link]

# Sequential execution

start_time = [Link]()

sequential_results = [fetch_url(url) for url in urls]


sequential_time = [Link]() - start_time

# Concurrent execution

start_time = [Link]()

with ThreadPoolExecutor(max_workers=3) as executor:

# Submit all tasks

futures = [[Link](fetch_url, url) for url in urls]

# Collect results as they complete

concurrent_results = []

for future in as_completed(futures):

result = [Link]()

concurrent_results.append(result)

concurrent_time = [Link]() - start_time

print(f"Sequential time: {sequential_time:.2f}s")

print(f"Concurrent time: {concurrent_time:.2f}s")

8.4 Async/Await (Modern Concurrency)

import asyncio

import aiohttp

import time

# Async functions

async def fetch_data(session, url):

async with [Link](url) as response:

return await [Link]()

async def main():


urls = [

"[Link]

"[Link]

"[Link]

async with [Link]() as session:

# Create tasks for concurrent execution

tasks = [fetch_data(session, url) for url in urls]

# Wait for all tasks to complete

results = await [Link](*tasks)

return results

# Run async code

if __name__ == "__main__":

start_time = [Link]()

results = [Link](main())

async_time = [Link]() - start_time

print(f"Async time: {async_time:.2f}s")

9. Performance Optimization

9.1 Profiling and Measurement

import time

import cProfile

from functools import wraps

# Timing decorator

def time_it(func):
@wraps(func)

def wrapper(*args, **kwargs):

start = [Link]()

result = func(*args, **kwargs)

end = [Link]()

print(f"{func.__name__} took {end - start:.4f} seconds")

return result

return wrapper

# Memory usage tracking

import tracemalloc

def track_memory(func):

@wraps(func)

def wrapper(*args, **kwargs):

[Link]()

result = func(*args, **kwargs)

current, peak = tracemalloc.get_traced_memory()

[Link]()

print(f"{func.__name__} - Current: {current / 1024 / 1024:.2f} MB, Peak: {peak / 1024 / 1024:.2f} MB")

return result

return wrapper

@time_it

@track_memory

def inefficient_sum(n):

total = 0

for i in range(n):

total += i
return total

@time_it

@track_memory

def efficient_sum(n):

return n * (n - 1) // 2

# Profile with cProfile

def profile_function():

[Link]('inefficient_sum(1000000)')

9.2 Optimization Techniques

# List comprehensions vs loops

import timeit

# Inefficient

def square_numbers_loop(numbers):

result = []

for num in numbers:

[Link](num ** 2)

return result

# Efficient

def square_numbers_comprehension(numbers):

return [num ** 2 for num in numbers]

# Generator expressions (memory efficient)

def square_numbers_generator(numbers):

return (num ** 2 for num in numbers)


# Pre-compile regex patterns

import re

# Inefficient (compiles pattern each time)

def find_emails_inefficient(texts):

results = []

for text in texts:

matches = [Link](r'\w+@\w+\.\w+', text)

[Link](matches)

return results

# Efficient (pre-compiled pattern)

EMAIL_PATTERN = [Link](r'\w+@\w+\.\w+')

def find_emails_efficient(texts):

results = []

for text in texts:

matches = EMAIL_PATTERN.findall(text)

[Link](matches)

return results

# Use sets for membership testing

def find_common_efficient(list1, list2):

set2 = set(list2) # Convert to set once

return [item for item in list1 if item in set2]

9.3 Caching and Memoization

from functools import lru_cache, cache

import time
# LRU Cache (Least Recently Used)

@lru_cache(maxsize=128)

def fibonacci(n):

if n < 2:

return n

return fibonacci(n-1) + fibonacci(n-2)

# Simple cache (Python 3.9+)

@cache

def expensive_computation(x, y):

[Link](1) # Simulate expensive operation

return x * y + x ** y

# Custom caching decorator

def simple_cache(func):

cache_dict = {}

@wraps(func)

def wrapper(*args, **kwargs):

key = str(args) + str(sorted([Link]()))

if key not in cache_dict:

cache_dict[key] = func(*args, **kwargs)

return cache_dict[key]

return wrapper

@simple_cache

def slow_function(n):

[Link](1)
return n ** 2

10. Design Patterns & Interfaces

10.1 Common Design Patterns

# Singleton Pattern

class Singleton:

_instance = None

_initialized = False

def __new__(cls):

if cls._instance is None:

cls._instance = super().__new__(cls)

return cls._instance

def __init__(self):

if not self._initialized:

[Link] = []

self._initialized = True

# Factory Pattern

from abc import ABC, abstractmethod

class Animal(ABC):

@abstractmethod

def make_sound(self):

pass

class Dog(Animal):

def make_sound(self):
return "Woof!"

class Cat(Animal):

def make_sound(self):

return "Meow!"

class AnimalFactory:

@staticmethod

def create_animal(animal_type):

if animal_type.lower() == "dog":

return Dog()

elif animal_type.lower() == "cat":

return Cat()

else:

raise ValueError(f"Unknown animal type: {animal_type}")

# Observer Pattern

class Subject:

def __init__(self):

self._observers = []

self._state = None

def attach(self, observer):

self._observers.append(observer)

def detach(self, observer):

self._observers.remove(observer)

def notify(self):
for observer in self._observers:

[Link](self._state)

def set_state(self, state):

self._state = state

[Link]()

class Observer:

def __init__(self, name):

[Link] = name

def update(self, state):

print(f"{[Link]} received update: {state}")

10.2 Interface Design with Protocols

from typing import Protocol, runtime_checkable

# Define interfaces using Protocol

@runtime_checkable

class EmailSender(Protocol):

def send_email(self, to: str, subject: str, body: str) -> bool:

...

@runtime_checkable

class EmailFetcher(Protocol):

def fetch_emails(self) -> list:

...

# Implementations

class GmailClient:
def send_email(self, to: str, subject: str, body: str) -> bool:

print(f"Sending email to {to}: {subject}")

return True

def fetch_emails(self) -> list:

print("Fetching emails from Gmail")

return ["email1", "email2"]

class OutlookClient:

def send_email(self, to: str, subject: str, body: str) -> bool:

print(f"Sending via Outlook to {to}: {subject}")

return True

def fetch_emails(self) -> list:

print("Fetching emails from Outlook")

return ["email1", "email2", "email3"]

# Usage with interface

def process_emails(client: EmailFetcher & EmailSender):

emails = client.fetch_emails()

client.send_email("admin@[Link]", "Report", f"Processed {len(emails)} emails")

# Works with any implementation

gmail = GmailClient()

outlook = OutlookClient()

process_emails(gmail)

process_emails(outlook)

10.3 Dependency Injection


from abc import ABC, abstractmethod

# Abstract interfaces

class DatabaseInterface(ABC):

@abstractmethod

def save(self, data): pass

@abstractmethod

def fetch(self, id): pass

class LoggerInterface(ABC):

@abstractmethod

def log(self, message): pass

# Concrete implementations

class MySQLDatabase(DatabaseInterface):

def save(self, data):

print(f"Saving to MySQL: {data}")

def fetch(self, id):

return f"Data from MySQL for ID: {id}"

class FileLogger(LoggerInterface):

def log(self, message):

print(f"Log to file: {message}")

# Service that depends on interfaces

class UserService:

def __init__(self, database: DatabaseInterface, logger: LoggerInterface):


[Link] = database

[Link] = logger

def create_user(self, user_data):

[Link](f"Creating user: {user_data}")

[Link](user_data)

[Link]("User created successfully")

# Dependency injection in action

database = MySQLDatabase()

logger = FileLogger()

user_service = UserService(database, logger)

user_service.create_user({"name": "Alice", "email": "alice@[Link]"})

11. Email Processing & Automation

11.1 Email Handling with imaplib

import imaplib

import email

from [Link] import MIMEText

from [Link] import MIMEMultipart

import smtplib

from dataclasses import dataclass

from typing import List, Optional

@dataclass

class Email:

sender: str

recipient: str
subject: str

body: str

date: str

message_id: str

class EmailClient:

def __init__(self, imap_server: str, smtp_server: str, username: str, password: str):

self.imap_server = imap_server

self.smtp_server = smtp_server

[Link] = username

[Link] = password

def fetch_emails(self, folder: str = "INBOX", limit: int = 10) -> List[Email]:

"""Fetch emails from the specified folder"""

emails = []

# Connect to IMAP server

with imaplib.IMAP4_SSL(self.imap_server) as mail:

[Link]([Link], [Link])

[Link](folder)

# Search for emails

status, messages = [Link](None, "ALL")

email_ids = messages[0].split()

# Fetch the most recent emails

for email_id in email_ids[-limit:]:

status, msg_data = [Link](email_id, "(RFC822)")


# Parse email

raw_email = msg_data[0][1]

email_message = email.message_from_bytes(raw_email)

# Extract email content

body = self._extract_body(email_message)

email_obj = Email(

sender=email_message.get("From", ""),

recipient=email_message.get("To", ""),

subject=email_message.get("Subject", ""),

body=body,

date=email_message.get("Date", ""),

message_id=email_message.get("Message-ID", "")

[Link](email_obj)

return emails

def _extract_body(self, email_message) -> str:

"""Extract plain text body from email message"""

body = ""

if email_message.is_multipart():

for part in email_message.walk():

if part.get_content_type() == "text/plain":

body = part.get_payload(decode=True).decode()

break

else:
body = email_message.get_payload(decode=True).decode()

return body

def send_email(self, to: str, subject: str, body: str, cc: List[str] = None) -> bool:

"""Send an email"""

try:

# Create message

msg = MIMEMultipart()

msg['From'] = [Link]

msg['To'] = to

msg['Subject'] = subject

if cc:

msg['Cc'] = ', '.join(cc)

# Attach body

[Link](MIMEText(body, 'plain'))

# Send email

with smtplib.SMTP_SSL(self.smtp_server, 465) as server:

[Link]([Link], [Link])

text = msg.as_string()

recipients = [to]

if cc:

[Link](cc)

[Link]([Link], recipients, text)


return True

except Exception as e:

print(f"Error sending email: {e}")

return False

# Usage example

# email_client = EmailClient(

# imap_server="[Link]",

# smtp_server="[Link]",

# username="your_email@[Link]",

# password="your_app_password"

#)

11.2 Advanced Email Processing

import re

from [Link] import ThreadPoolExecutor, as_completed

from typing import Dict, Callable

from collections import defaultdict

class EmailProcessor:

def __init__(self, email_client: EmailClient):

self.email_client = email_client

[Link] = []

[Link] = []

# Pre-compiled regex patterns for efficiency

[Link] = {

'email': [Link](r'\b[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\.[A-Z|a-z]{2,}\b'),
'phone': [Link](r'\(?\d{3}\)?[-.\s]?\d{3}[-.\s]?\d{4}'),

'url': [Link](r'http[s]?://(?:[a-zA-Z]|[0-9]|[$-_@.&+]|[!*\(\),]|(?:%[0-9a-fA-F][0-9a-fA-F]))+'),

'signature': [Link](r'(?:Best regards?|Sincerely|Thanks?|Regards|Kind regards),?\s*\n\s*([A-Za-


z\s]+)', [Link])

def add_filter(self, filter_func: Callable[[Email], bool]):

"""Add a filter function to determine which emails to process"""

[Link](filter_func)

def add_processor(self, processor_func: Callable[[Email], Dict]):

"""Add a processor function to extract data from emails"""

[Link](processor_func)

def filter_emails(self, emails: List[Email]) -> List[Email]:

"""Apply all filters to email list"""

filtered_emails = emails

for filter_func in [Link]:

filtered_emails = [email for email in filtered_emails if filter_func(email)]

return filtered_emails

def extract_contact_info(self, email: Email) -> Dict[str, List[str]]:

"""Extract contact information from email"""

return {

'emails': [Link]['email'].findall([Link]),

'phones': [Link]['phone'].findall([Link]),

'urls': [Link]['url'].findall([Link])
}

def extract_sender_name(self, email: Email) -> Optional[str]:

"""Extract sender name from email signature"""

match = [Link]['signature'].search([Link])

return [Link](1).strip() if match else None

def categorize_email(self, email: Email) -> str:

"""Categorize email based on content"""

subject_lower = [Link]()

body_lower = [Link]()

# Define categories and keywords

categories = {

'job_application': ['application', 'resume', 'cv', 'position', 'job'],

'support_request': ['help', 'issue', 'problem', 'error', 'bug'],

'sales_inquiry': ['price', 'quote', 'purchase', 'buy', 'cost'],

'meeting_request': ['meeting', 'schedule', 'appointment', 'calendar'],

'newsletter': ['unsubscribe', 'newsletter', 'update', 'news']

for category, keywords in [Link]():

if any(keyword in subject_lower or keyword in body_lower for keyword in keywords):

return category

return 'general'

def process_emails_batch(self, emails: List[Email], max_workers: int = 10) -> Dict[str, any]:

"""Process emails in parallel"""


results = {

'total_processed': 0,

'categories': defaultdict(int),

'contact_info': [],

'sender_names': [],

'errors': []

with ThreadPoolExecutor(max_workers=max_workers) as executor:

# Submit processing tasks

futures = {

[Link](self._process_single_email, email): email

for email in emails

# Collect results as they complete

for future in as_completed(futures):

email = futures[future]

try:

email_result = [Link]()

# Aggregate results

results['total_processed'] += 1

results['categories'][email_result['category']] += 1

if email_result['contact_info']:

results['contact_info'].append(email_result['contact_info'])

if email_result['sender_name']:
results['sender_names'].append(email_result['sender_name'])

except Exception as e:

results['errors'].append(f"Error processing email from {[Link]}: {e}")

return dict(results)

def _process_single_email(self, email: Email) -> Dict[str, any]:

"""Process a single email and extract information"""

return {

'category': self.categorize_email(email),

'contact_info': self.extract_contact_info(email),

'sender_name': self.extract_sender_name(email)

def generate_auto_reply(self, email: Email, template_name: str = "default") -> str:

"""Generate automated reply based on email content"""

templates = {

'job_application': """

Dear {sender_name},

Thank you for your interest in our position. We have received your application and will review it carefully.

We will contact you within 5-7 business days regarding the next steps.

Best regards,

HR Team

""",

'support_request': """
Dear {sender_name},

Thank you for contacting our support team. We have received your request and assigned it ticket number
#{ticket_id}.

Our team will respond within 24 hours.

Best regards,

Support Team

""",

'default': """

Dear {sender_name},

Thank you for your email. We have received your message and will respond as soon as possible.

Best regards,

Customer Service Team

"""

sender_name = self.extract_sender_name(email) or "Valued Customer"

category = self.categorize_email(email)

template = [Link](category, templates['default'])

# Generate ticket ID for support requests

import random

ticket_id = [Link](100000, 999999)

return [Link](sender_name=sender_name, ticket_id=ticket_id).strip()


11.3 Email Analytics and Reporting

import [Link] as plt

import pandas as pd

from datetime import datetime, timedelta

from collections import Counter

import seaborn as sns

class EmailAnalytics:

def __init__(self, emails: List[Email]):

[Link] = emails

[Link] = self._emails_to_dataframe()

def _emails_to_dataframe(self) -> [Link]:

"""Convert email list to pandas DataFrame"""

data = []

for email in [Link]:

# Parse date

try:

date_obj = [Link]([Link][:25], "%a, %d %b %Y %H:%M:%S")

except:

date_obj = [Link]()

[Link]({

'sender': [Link],

'subject': [Link],

'date': date_obj,

'body_length': len([Link]),

'word_count': len([Link]()),

'has_attachments': 'attachment' in [Link]()


})

return [Link](data)

def get_email_volume_by_hour(self) -> Dict[int, int]:

"""Get email volume distribution by hour of day"""

return [Link]['date'].[Link].value_counts().to_dict()

def get_top_senders(self, limit: int = 10) -> Dict[str, int]:

"""Get top email senders"""

return [Link]['sender'].value_counts().head(limit).to_dict()

def get_average_response_time(self) -> float:

"""Calculate average time between emails (mock implementation)"""

sorted_emails = [Link].sort_values('date')

time_diffs = sorted_emails['date'].diff().dt.total_seconds() / 3600 # in hours

return time_diffs.mean()

def generate_report(self) -> str:

"""Generate comprehensive email analytics report"""

report = f"""

EMAIL ANALYTICS REPORT

=====================

Total Emails: {len([Link])}

Date Range: {[Link]['date'].min()} to {[Link]['date'].max()}

VOLUME METRICS:

- Average emails per day: {len([Link]) / max(1, ([Link]['date'].max() - [Link]['date'].min()).days):.1f}


- Peak hour: {[Link]['date'].[Link]().iloc[0]}:00

- Average email length: {[Link]['word_count'].mean():.0f} words

TOP SENDERS:

{chr(10).join([f"- {sender}: {count} emails" for sender, count in self.get_top_senders(5).items()])}

CONTENT ANALYSIS:

- Emails with attachments: {[Link]['has_attachments'].sum()}


({[Link]['has_attachments'].mean()*100:.1f}%)

- Longest email: {[Link]['word_count'].max()} words

- Shortest email: {[Link]['word_count'].min()} words

"""

return [Link]()

def plot_email_trends(self):

"""Create visualization of email trends"""

fig, axes = [Link](2, 2, figsize=(15, 10))

# Daily email volume

daily_volume = [Link]([Link]['date'].[Link]).size()

axes[0, 0].plot(daily_volume.index, daily_volume.values)

axes[0, 0].set_title('Daily Email Volume')

axes[0, 0].set_xlabel('Date')

axes[0, 0].set_ylabel('Number of Emails')

# Hourly distribution

hourly_dist = [Link]['date'].[Link].value_counts().sort_index()

axes[0, 1].bar(hourly_dist.index, hourly_dist.values)

axes[0, 1].set_title('Email Distribution by Hour')


axes[0, 1].set_xlabel('Hour of Day')

axes[0, 1].set_ylabel('Number of Emails')

# Email length distribution

axes[1, 0].hist([Link]['word_count'], bins=30, alpha=0.7)

axes[1, 0].set_title('Email Length Distribution')

axes[1, 0].set_xlabel('Word Count')

axes[1, 0].set_ylabel('Frequency')

# Top senders

top_senders = self.get_top_senders(10)

axes[1, 1].barh(list(top_senders.keys()), list(top_senders.values()))

axes[1, 1].set_title('Top 10 Email Senders')

axes[1, 1].set_xlabel('Number of Emails')

plt.tight_layout()

[Link]()

# Usage example

def demo_email_processing():

# Mock email data for demonstration

sample_emails = [

Email("john@[Link]", "hr@[Link]", "Job Application - Software Engineer",

"Dear Hiring Manager,\n\nI am writing to apply for the software engineer position...\n\nBest
regards,\nJohn Smith",

"Mon, 01 Jan 2024 10:30:00", "msg001"),

Email("support@[Link]", "help@[Link]", "Technical Issue - Login Problem",

"Hello,\n\nI'm having trouble logging into my account...\n\nThanks,\nSarah Johnson",

"Mon, 01 Jan 2024 14:15:00", "msg002")


]

# Create processor

processor = EmailProcessor(None)

# Add filters

processor.add_filter(lambda email: len([Link]) > 50) # Filter short emails

# Process emails

results = processor.process_emails_batch(sample_emails)

print("Processing Results:", results)

# Generate analytics

analytics = EmailAnalytics(sample_emails)

print(analytics.generate_report())

12. Advanced Projects

12.1 Complete Email Automation System

import asyncio

import aiohttp

from typing import List, Dict, Optional, Callable

from dataclasses import dataclass, field

from datetime import datetime, timedelta

import json

import logging

# Configure logging

[Link](level=[Link])

logger = [Link](__name__)
@dataclass

class EmailRule:

"""Represents a rule for email processing"""

name: str

condition: Callable[[Email], bool]

action: Callable[[Email], bool]

priority: int = 0

enabled: bool = True

created_at: datetime = field(default_factory=[Link])

class EmailAutomationEngine:

"""Advanced email automation system"""

def __init__(self, email_client: EmailClient):

self.email_client = email_client

[Link]: List[EmailRule] = []

[Link] = {

'emails_processed': 0,

'rules_executed': 0,

'errors': 0,

'start_time': [Link]()

def add_rule(self, rule: EmailRule):

"""Add an automation rule"""

[Link](rule)

# Sort rules by priority (higher priority first)

[Link](key=lambda r: [Link], reverse=True)


[Link](f"Added rule: {[Link]} (priority: {[Link]})")

def remove_rule(self, rule_name: str):

"""Remove a rule by name"""

[Link] = [rule for rule in [Link] if [Link] != rule_name]

[Link](f"Removed rule: {rule_name}")

async def process_emails_async(self, check_interval: int = 300):

"""Continuously process emails with async support"""

[Link](f"Starting email automation (check interval: {check_interval}s)")

while True:

try:

# Fetch new emails

emails = self.email_client.fetch_emails(limit=50)

[Link](f"Fetched {len(emails)} emails")

# Process emails with rules

await self._apply_rules_async(emails)

# Wait before next check

await [Link](check_interval)

except Exception as e:

[Link](f"Error in email processing loop: {e}")

[Link]['errors'] += 1

await [Link](60) # Wait 1 minute before retrying

async def _apply_rules_async(self, emails: List[Email]):


"""Apply rules to emails asynchronously"""

tasks = []

for email in emails:

for rule in [Link]:

if [Link]:

task = asyncio.create_task(self._execute_rule(email, rule))

[Link](task)

# Execute all rules concurrently

await [Link](*tasks, return_exceptions=True)

async def _execute_rule(self, email: Email, rule: EmailRule):

"""Execute a single rule on an email"""

try:

if [Link](email):

[Link](f"Executing rule '{[Link]}' for email: {[Link]}")

success = await asyncio.to_thread([Link], email)

if success:

[Link]['rules_executed'] += 1

[Link](f"Rule '{[Link]}' executed successfully")

else:

[Link](f"Rule '{[Link]}' failed to execute")

except Exception as e:

[Link](f"Error executing rule '{[Link]}': {e}")

[Link]['errors'] += 1
def get_stats(self) -> Dict:

"""Get automation statistics"""

runtime = [Link]() - [Link]['start_time']

return {

**[Link],

'runtime_hours': runtime.total_seconds() / 3600,

'emails_per_hour': [Link]['emails_processed'] / max(1, runtime.total_seconds() / 3600),

'active_rules': len([rule for rule in [Link] if [Link]])

# Example rules and usage

class EmailRules:

"""Collection of common email automation rules"""

@staticmethod

def create_job_application_rule(email_client: EmailClient) -> EmailRule:

"""Auto-respond to job applications"""

def condition(email: Email) -> bool:

keywords = ['job', 'application', 'resume', 'position', 'career']

subject_lower = [Link]()

return any(keyword in subject_lower for keyword in keywords)

def action(email: Email) -> bool:

response = f"""

Dear Applicant,

Thank you for your interest in our company. We have received your job application

and will review it carefully.


Our HR team will contact you within 5-7 business days if your qualifications

match our current openings.

Best regards,

Human Resources Team

""".strip()

return email_client.send_email(

to=[Link],

subject=f"Re: {[Link]}",

body=response

return EmailRule(

name="job_application_auto_reply",

condition=condition,

action=action,

priority=10

@staticmethod

def create_spam_filter_rule() -> EmailRule:

"""Mark suspicious emails as spam"""

def condition(email: Email) -> bool:

spam_indicators = [

'urgent', 'act now', 'limited time', 'click here',

'free money', 'guaranteed', 'no risk'

content = ([Link] + ' ' + [Link]).lower()


return sum(indicator in content for indicator in spam_indicators) >= 2

def action(email: Email) -> bool:

[Link](f"Potential spam detected from {[Link]}: {[Link]}")

# In a real system, you would move to spam folder or flag

return True

return EmailRule(

name="spam_filter",

condition=condition,

action=action,

priority=100 # High priority

# Complete demo system

async def demo_automation_system():

"""Demonstrate the complete email automation system"""

# Create email client (mock for demo)

class MockEmailClient:

def fetch_emails(self, limit=10):

return [

Email("applicant@[Link]", "hr@[Link]",

"Job Application - Senior Developer",

"I would like to apply for the senior developer position...",

[Link]().isoformat(), "msg001"),

Email("spam@[Link]", "info@[Link]",

"URGENT: Act Now! Free Money Guaranteed!",

"Click here for free money with no risk!",


[Link]().isoformat(), "msg002")

def send_email(self, to, subject, body):

print(f"EMAIL SENT TO {to}: {subject}")

return True

# Create automation engine

email_client = MockEmailClient()

automation = EmailAutomationEngine(email_client)

# Add rules

job_rule = EmailRules.create_job_application_rule(email_client)

spam_rule = EmailRules.create_spam_filter_rule()

automation.add_rule(job_rule)

automation.add_rule(spam_rule)

# Run one cycle for demo

emails = email_client.fetch_emails()

await automation._apply_rules_async(emails)

# Print statistics

print("\nAutomation Statistics:")

print([Link](automation.get_stats(), indent=2, default=str))

# Run the demo

if __name__ == "__main__":

[Link](demo_automation_system())
12.2 Performance Monitoring and Optimization

import psutil

import threading

from contextlib import contextmanager

from typing import Generator, Dict, Any

import json

class PerformanceMonitor:

"""Monitor system and application performance"""

def __init__(self):

[Link] = {}

[Link] = False

self.monitor_thread = None

def start_monitoring(self, interval: float = 1.0):

"""Start background performance monitoring"""

if [Link]:

return

[Link] = True

self.monitor_thread = [Link](

target=self._monitor_loop,

args=(interval,),

daemon=True

self.monitor_thread.start()

[Link]("Performance monitoring started")


def stop_monitoring(self):

"""Stop background monitoring"""

[Link] = False

if self.monitor_thread:

self.monitor_thread.join()

[Link]("Performance monitoring stopped")

def _monitor_loop(self, interval: float):

"""Background monitoring loop"""

while [Link]:

[Link]({

'timestamp': [Link]().isoformat(),

'cpu_percent': psutil.cpu_percent(),

'memory_percent': psutil.virtual_memory().percent,

'disk_io': psutil.disk_io_counters()._asdict() if psutil.disk_io_counters() else {},

'network_io': psutil.net_io_counters()._asdict()

})

[Link](interval)

@contextmanager

def measure_operation(self, operation_name: str) -> Generator[Dict[str, Any], None, None]:

"""Context manager to measure operation performance"""

start_time = [Link]()

start_memory = [Link]().memory_info().rss

operation_metrics = {

'operation': operation_name,

'start_time': start_time

}
try:

yield operation_metrics

finally:

end_time = [Link]()

end_memory = [Link]().memory_info().rss

operation_metrics.update({

'duration': end_time - start_time,

'memory_delta': end_memory - start_memory,

'end_time': end_time

})

[Link](f"Operation '{operation_name}' completed in {operation_metrics['duration']:.2f}s")

def get_current_metrics(self) -> Dict[str, Any]:

"""Get current system metrics"""

return [Link]()

# Enhanced EmailProcessor with monitoring

class MonitoredEmailProcessor(EmailProcessor):

"""EmailProcessor with built-in performance monitoring"""

def __init__(self, email_client: EmailClient):

super().__init__(email_client)

[Link] = PerformanceMonitor()

self.operation_stats = defaultdict(list)

def process_emails_with_monitoring(self) -> Dict[str, Any]:


"""Process emails with comprehensive monitoring"""

[Link].start_monitoring()

try:

with [Link].measure_operation("full_email_processing") as metrics:

# Fetch emails

with [Link].measure_operation("email_fetch") as fetch_metrics:

emails = self.email_client.fetch_emails()

fetch_metrics['email_count'] = len(emails)

# Filter emails

with [Link].measure_operation("email_filtering") as filter_metrics:

filtered_emails = self.filter_emails(emails)

filter_metrics['filtered_count'] = len(filtered_emails)

# Process emails

with [Link].measure_operation("email_batch_processing") as process_metrics:

results = self.process_emails_batch(filtered_emails)

process_metrics['processed_count'] = results['responses_sent']

# Compile final results

final_results = {

**results,

'performance_metrics': {

'total_duration': metrics['duration'],

'fetch_duration': fetch_metrics['duration'],

'filter_duration': filter_metrics['duration'],

'process_duration': process_metrics['duration'],

'emails_per_second': len(filtered_emails) / max(0.001, process_metrics['duration']),


'system_metrics': [Link].get_current_metrics()

return final_results

finally:

[Link].stop_monitoring()

# Example usage and testing

def benchmark_email_processing():

"""Benchmark different email processing approaches"""

# Mock data for testing

mock_emails = [

Email(f"user{i}@[Link]", "system@[Link]",

f"Test Email {i} - pseudo internship interest",

f"Hello,\n\nThis is test email {i}.\n\nBest regards,\nUser {i}",

[Link]().isoformat(), f"msg{i:03d}")

for i in range(100)

class MockEmailClient:

def __init__(self, emails):

[Link] = emails

def fetch_emails(self, limit=None):

return [Link][:limit] if limit else [Link]


def send_email(self, to, subject, body):

[Link](0.01) # Simulate network delay

return True

# Test different configurations

configurations = [

{"max_workers": 1, "name": "Sequential"},

{"max_workers": 5, "name": "5 Workers"},

{"max_workers": 10, "name": "10 Workers"},

{"max_workers": 20, "name": "20 Workers"}

results = {}

for config in configurations:

print(f"\n--- Testing {config['name']} ---")

email_client = MockEmailClient(mock_emails)

processor = MonitoredEmailProcessor(email_client)

# Override max_workers for this test

original_method = processor.process_emails_batch

def test_process(emails, max_workers=config['max_workers']):

return original_method(emails, max_workers)

processor.process_emails_batch = test_process

# Run test

result = processor.process_emails_with_monitoring()

results[config['name']] = result['performance_metrics']
print(f"Duration: {result['performance_metrics']['total_duration']:.2f}s")

print(f"Emails/sec: {result['performance_metrics']['emails_per_second']:.1f}")

# Print comparison

print("\n" + "="*50)

print("PERFORMANCE COMPARISON")

print("="*50)

for name, metrics in [Link]():

print(f"{name:15} | {metrics['total_duration']:6.2f}s | {metrics['emails_per_second']:6.1f}/sec")

if __name__ == "__main__":

benchmark_email_processing()

12.3 Machine Learning Integration

import numpy as np

from sklearn.feature_extraction.text import TfidfVectorizer

from sklearn.naive_bayes import MultinomialNB

from [Link] import Pipeline

from sklearn.model_selection import train_test_split

from [Link] import classification_report, accuracy_score

import pickle

import os

from typing import Tuple, List

class EmailClassifier:

"""Machine learning-based email classifier"""

def __init__(self, model_path: str = "email_classifier.pkl"):


self.model_path = model_path

[Link] = None

[Link] = []

self.is_trained = False

def prepare_training_data(self, emails: List[Email]) -> Tuple[List[str], List[str]]:

"""Prepare training data from emails"""

texts = []

labels = []

for email in emails:

# Combine subject and body for better classification

full_text = f"{[Link]} {[Link]}"

[Link](full_text)

# Use a simple rule-based labeling for demonstration

# In real scenarios, you would have manually labeled data

label = self._auto_label_email(email)

[Link](label)

return texts, labels

def _auto_label_email(self, email: Email) -> str:

"""Auto-label emails based on keywords (for demo purposes)"""

subject_body = ([Link] + " " + [Link]).lower()

if any(word in subject_body for word in ['job', 'application', 'resume', 'position']):

return 'job_application'

elif any(word in subject_body for word in ['support', 'help', 'issue', 'problem']):


return 'support'

elif any(word in subject_body for word in ['meeting', 'schedule', 'appointment']):

return 'meeting'

elif any(word in subject_body for word in ['invoice', 'payment', 'bill', 'purchase']):

return 'finance'

else:

return 'general'

def train(self, emails: List[Email], test_size: float = 0.2):

"""Train the email classifier"""

print("Preparing training data...")

texts, labels = self.prepare_training_data(emails)

# Split data

X_train, X_test, y_train, y_test = train_test_split(

texts, labels, test_size=test_size, random_state=42, stratify=labels

print(f"Training on {len(X_train)} samples, testing on {len(X_test)} samples")

# Create pipeline with TF-IDF and Naive Bayes

[Link] = Pipeline([

('tfidf', TfidfVectorizer(

max_features=5000,

stop_words='english',

ngram_range=(1, 2),

min_df=2

)),

('classifier', MultinomialNB(alpha=0.1))
])

# Train the model

print("Training classifier...")

[Link](X_train, y_train)

# Evaluate

y_pred = [Link](X_test)

accuracy = accuracy_score(y_test, y_pred)

print(f"Training completed! Accuracy: {accuracy:.3f}")

print("\nClassification Report:")

print(classification_report(y_test, y_pred))

# Store categories and mark as trained

[Link] = list(set(labels))

self.is_trained = True

# Save model

self.save_model()

def predict(self, email: Email) -> Tuple[str, float]:

"""Predict email category and confidence"""

if not self.is_trained:

raise ValueError("Model must be trained before making predictions")

full_text = f"{[Link]} {[Link]}"

prediction = [Link]([full_text])[0]
# Get prediction probabilities

probabilities = [Link].predict_proba([full_text])[0]

confidence = max(probabilities)

return prediction, confidence

def predict_batch(self, emails: List[Email]) -> List[Tuple[str, float]]:

"""Predict categories for multiple emails"""

if not self.is_trained:

raise ValueError("Model must be trained before making predictions")

texts = [f"{[Link]} {[Link]}" for email in emails]

predictions = [Link](texts)

probabilities = [Link].predict_proba(texts)

results = []

for pred, probs in zip(predictions, probabilities):

confidence = max(probs)

[Link]((pred, confidence))

return results

def save_model(self):

"""Save trained model to disk"""

if [Link] is None:

raise ValueError("No trained model to save")

model_data = {

'pipeline': [Link],
'categories': [Link],

'is_trained': self.is_trained

with open(self.model_path, 'wb') as f:

[Link](model_data, f)

print(f"Model saved to {self.model_path}")

def load_model(self):

"""Load trained model from disk"""

if not [Link](self.model_path):

raise FileNotFoundError(f"Model file {self.model_path} not found")

with open(self.model_path, 'rb') as f:

model_data = [Link](f)

[Link] = model_data['pipeline']

[Link] = model_data['categories']

self.is_trained = model_data['is_trained']

print(f"Model loaded from {self.model_path}")

class SmartEmailProcessor(EmailProcessor):

"""Email processor enhanced with machine learning"""

def __init__(self, email_client: EmailClient):

super().__init__(email_client)

[Link] = EmailClassifier()
self.smart_responses = {

'job_application': self._generate_job_response,

'support': self._generate_support_response,

'meeting': self._generate_meeting_response,

'finance': self._generate_finance_response,

'general': self._generate_general_response

def train_classifier(self, training_emails: List[Email]):

"""Train the ML classifier with historical emails"""

print("Training email classifier...")

[Link](training_emails)

def process_emails_smart(self) -> Dict[str, Any]:

"""Process emails using ML classification"""

# Fetch emails

emails = self.email_client.fetch_emails()

filtered_emails = self.filter_emails(emails)

# Classify emails

classifications = [Link].predict_batch(filtered_emails)

# Process each email based on its classification

results = {

'total_emails': len(emails),

'filtered_emails': len(filtered_emails),

'classifications': {},

'responses_sent': 0,

'high_confidence_predictions': 0
}

for email, (category, confidence) in zip(filtered_emails, classifications):

# Track classifications

if category not in results['classifications']:

results['classifications'][category] = 0

results['classifications'][category] += 1

# Track high confidence predictions

if confidence > 0.8:

results['high_confidence_predictions'] += 1

# Generate and send smart response

if confidence > 0.6: # Only respond if reasonably confident

response = self.smart_responses[category](email, confidence)

if self.email_client.send_email(

to=[Link],

subject=f"Re: {[Link]}",

body=response

):

results['responses_sent'] += 1

return results

def _generate_job_response(self, email: Email, confidence: float) -> str:

name = self.extract_name_from_email([Link]) or "Applicant"

return f"""Dear {name},

Thank you for your interest in our company and for submitting your job application.
Our HR team has received your application and will review it thoroughly. We appreciate

your interest in joining our team and will contact you within 5-7 business days

regarding the next steps in our hiring process.

If you have any questions in the meantime, please don't hesitate to contact us.

Best regards,

Human Resources Team

---

This is an automated response generated with {confidence*100:.1f}% confidence.

"""

def _generate_support_response(self, email: Email, confidence: float) -> str:

name = self.extract_name_from_email([Link]) or "Valued Customer"

import random

ticket_id = [Link](100000, 999999)

return f"""Dear {name},

Thank you for contacting our support team. We have received your request and

assigned it ticket number #{ticket_id}.

Our technical support specialists will review your issue and respond within

24 hours during business hours.

For urgent matters, please call our support hotline at 1-800-SUPPORT.


Best regards,

Technical Support Team

---

Ticket ID: #{ticket_id}

Confidence: {confidence*100:.1f}%

"""

def _generate_meeting_response(self, email: Email, confidence: float) -> str:

name = self.extract_name_from_email([Link]) or "Colleague"

return f"""Dear {name},

Thank you for your meeting request. I have received your message and will

review my calendar to find a suitable time.

I will respond with available time slots within 24 hours. Please let me know

if you have any specific time preferences or requirements for our meeting.

Best regards,

Assistant

---

Auto-classified as meeting request ({confidence*100:.1f}% confidence)

"""

def _generate_finance_response(self, email: Email, confidence: float) -> str:

name = self.extract_name_from_email([Link]) or "Customer"

return f"""Dear {name},


Thank you for your financial inquiry. We have received your message regarding

billing/payment matters.

Our accounting department will review your request and respond within 2-3

business days. For immediate assistance with urgent payment matters, please

contact our billing department directly at billing@[Link].

Best regards,

Finance Team

---

Classified as finance-related ({confidence*100:.1f}% confidence)

"""

def _generate_general_response(self, email: Email, confidence: float) -> str:

name = self.extract_name_from_email([Link]) or "Valued Contact"

return f"""Dear {name},

Thank you for your email. We have received your message and will review it carefully.

Someone from our team will respond to you within 2-3 business days. If your

matter is urgent, please don't hesitate to call us directly.

Best regards,

Customer Service Team

---

General inquiry (classified with {confidence*100:.1f}% confidence)

"""
# Demo and testing

def demo_ml_email_processing():

"""Demonstrate ML-enhanced email processing"""

# Create sample training data

training_emails = [

Email("job1@[Link]", "hr@[Link]", "Software Engineer Application",

"Dear HR, I am applying for the software engineer position. Please find my resume attached. Best
regards, John Smith",

"2024-01-01", "1"),

Email("support1@[Link]", "help@[Link]", "Login Issue",

"Hello, I cannot log into my account. Please help. Thanks, Sarah",

"2024-01-01", "2"),

Email("partner@[Link]", "meetings@[Link]", "Schedule Meeting",

"Hi, can we schedule a meeting next week to discuss the project? Regards, Mike",

"2024-01-01", "3"),

# Add more training examples...

# Mock email client

class MockMLClient:

def fetch_emails(self, limit=10):

return [

Email("newapplicant@[Link]", "hr@[Link]", "Job Application - Data Scientist",

"I would like to apply for the data scientist position posted on your website.",

"2024-01-02", "new1"),

Email("customer@[Link]", "support@[Link]", "Technical Problem",

"I'm experiencing issues with the software. It keeps crashing.",


"2024-01-02", "new2")

def send_email(self, to, subject, body):

print(f"\n--- EMAIL SENT TO {to} ---")

print(f"Subject: {subject}")

print(f"Body: {body[:200]}...")

return True

# Create and train smart processor

email_client = MockMLClient()

processor = SmartEmailProcessor(email_client)

print("Training ML classifier...")

processor.train_classifier(training_emails)

print("\nProcessing new emails with ML classification...")

results = processor.process_emails_smart()

print(f"\nResults: {[Link](results, indent=2)}")

if __name__ == "__main__":

demo_ml_email_processing()

Learning Path and Next Steps

Beginner Path (Weeks 1-4)

1. Week 1: Python fundamentals, variables, control structures

2. Week 2: Functions, basic OOP, classes and objects

3. Week 3: Data structures, lists, dictionaries, string processing


4. Week 4: File handling, basic error handling

Intermediate Path (Weeks 5-8)

1. Week 5: Advanced OOP, inheritance, polymorphism

2. Week 6: Regular expressions, text processing

3. Week 7: Type hints, modern Python features

4. Week 8: Basic threading and concurrency

Advanced Path (Weeks 9-12)

1. Week 9: Advanced concurrency, async/await

2. Week 10: Performance optimization, profiling

3. Week 11: Design patterns, interfaces

4. Week 12: Email processing and automation

Expert Path (Months 4-6)

1. Month 4: Machine learning integration, data science

2. Month 5: Web frameworks, APIs, databases

3. Month 6: System design, scalability, deployment

Practice Projects

1. Beginner: Personal task manager

2. Intermediate: Web scraper with email notifications

3. Advanced: Complete email automation system

4. Expert: ML-powered email classification service

Additional Resources

• Books: "Python Tricks" by Dan Bader, "Effective Python" by Brett Slatkin

• Practice: LeetCode, HackerRank, CodeWars

• Documentation: Official Python docs, PEP guidelines

• Communities: Reddit r/Python, Stack Overflow, Python Discord

Key Tips for Success

1. Practice daily: Write code every day, even if just for 30 minutes

2. Build projects: Apply concepts to real-world problems

3. Read others' code: Study open-source Python projects


4. Learn debugging: Master debugging tools and techniques

5. Stay updated: Follow Python news and new features

6. Join community: Participate in Python forums and discussions

This comprehensive guide covers everything from basic Python syntax to advanced email automation
with machine learning. Each section builds upon the previous one, ensuring a solid foundation for Python
development. Remember that mastering programming is a journey - be patient, practice consistently,
and don't hesitate to experiment with the code examples!

You might also like