No history yet

Advanced Python Architecture

Advanced Data Structures

When building AI systems, you often work with large datasets. Writing clean, efficient code to handle this data is crucial. While standard loops get the job done, Python offers more powerful tools called comprehensions for creating lists and dictionaries concisely.

Imagine you have a list of sensor readings and you need to filter out negative values and convert the rest from Celsius to Fahrenheit. A list comprehension can do this in a single, readable line.

celsius_readings = [22.5, -4.0, 15.8, 30.1, -1.2]

# Filter out negatives and convert in one line
fahrenheit_readings = [(reading * 9/5) + 32 for reading in celsius_readings if reading >= 0]

print(fahrenheit_readings)
# Output: [72.5, 60.44, 86.18]

Dictionary comprehensions are just as powerful. They are perfect for creating mappings or managing the state of objects in your system. For instance, you could create a dictionary that maps unique object IDs from a computer vision pipeline to their initial status.

object_ids = ["car_1", "person_3", "car_2"]

# Create a state dictionary for each object
state_mapping = {obj_id: 'tracking' for obj_id in object_ids}

print(state_mapping)
# Output: {'car_1': 'tracking', 'person_3': 'tracking', 'car_2': 'tracking'}

Organising AI with Objects

As AI projects grow, managing functions and data becomes complex. Object-Oriented Programming (OOP) provides a way to structure your code logically. It allows you to bundle data and the functions that operate on that data into single units called objects.

A Class is the blueprint for an object. For an AI application, you might create a VisionModel class. This blueprint defines what data the model needs (like model weights) and what it can do (like make predictions).

An Object is a specific instance created from that class. You could create two objects from your VisionModel class: one for detecting faces and another for detecting cars. Each would be a separate object with its own configuration, but both would share the same underlying structure defined by the class.

Think of a class as a recipe for a cake, and an object as the actual cake you bake from that recipe.

When an object is created, a special method called __init__ is automatically run. This is the initialiser, where you set up the object's starting state. The self keyword is used inside a class to refer to the object instance itself. It lets you access the object's attributes and methods.

Here’s a simple VisionModel class. When we create an object from it, we pass a model_path, which __init__ then stores as an attribute of that specific object using self.

class VisionModel:
    def __init__(self, model_path):
        # 'self' refers to the specific object being created
        print(f"Initialising model from {model_path}")
        self.model_path = model_path
        # In a real scenario, you'd load the model weights here

    def predict(self, image):
        print(f"Running prediction on an image using {self.model_path}")
        # Prediction logic would go here
        return "prediction_result"

# Create an object (instance) of the VisionModel class
face_detector = VisionModel(model_path="/models/face_detector.pth")
face_detector.predict("my_image.jpg")

Inheritance is another key OOP principle. It allows you to create a new class that inherits all the methods and properties from an existing class. This is great for creating specialised versions of a general component.

For example, we can create an ObjectDetector class that inherits from our VisionModel. It gets the __init__ and predict methods for free, and we can add new methods or modify existing ones specifically for object detection.

# ObjectDetector inherits from VisionModel
class ObjectDetector(VisionModel):
    def draw_bounding_boxes(self, image, predictions):
        print("Drawing boxes around detected objects")
        # Logic to draw boxes on the image

# Create an ObjectDetector instance
car_detector = ObjectDetector(model_path="/models/car_detector.pth")

# It has its own methods...
car_detector.draw_bounding_boxes("image.jpg", [])

# ...and methods from its parent class, VisionModel
prediction = car_detector.predict("image.jpg")

Enhancing Functionality

Sometimes you want to add extra behaviour to a function, like logging when it runs or timing how long it takes. Python decorators let you do this without changing the function's code. A decorator is a function that wraps another function.

This is incredibly useful in AI, especially for real-time video processing where performance is critical. You can write a simple timer decorator to measure the execution time of any function in your pipeline.

import time

# This is the decorator
def timer(func):
    def wrapper(*args, **kwargs):
        start_time = time.time()
        result = func(*args, **kwargs)
        end_time = time.time()
        print(f"{func.__name__} ran in {end_time - start_time:.4f} seconds")
        return result
    return wrapper

# Apply the decorator to a function using the '@' symbol
@timer
def process_frame(frame_data):
    # Simulate a complex computer vision task
    time.sleep(0.5) 
    print("Frame processed.")

process_frame("some_frame_data")

# Output:
# Frame processed.
# process_frame ran in 0.5005 seconds

Professional Project Structure

Finally, how you organise your files matters. A clean directory structure makes your project easier to understand, maintain, and share. For an AI project, it's standard practice to separate your data, model logic, utility functions, and tests into different folders.

This modular approach, combined with OOP, allows you to build complex, reusable components. An __init__.py file in a directory tells Python it can be treated as a package, allowing you to import code from it cleanly across your project.

my_vision_project/
├── data/
│   ├── raw/
│   └── processed/
├── models/
│   └── saved_model.pth
├── src/
│   ├── __init__.py
│   ├── data_processing.py
│   ├── model.py
│   └── utils.py
├── tests/
│   ├── __init__.py
│   └── test_model.py
├── main.py
└── requirements.txt

In this structure, main.py would be the entry point to run your application. It would import classes and functions from the src directory to build and run the AI pipeline. This organisation keeps everything tidy and scalable.

Ready to test your knowledge on these architectural concepts?

Quiz Questions 1/6

In Object-Oriented Programming, what is the primary role of the __init__ method in a Python class?

Quiz Questions 2/6

Which line of code correctly uses a list comprehension to filter a list of temperatures (in Celsius) to include only positive values and convert them to Fahrenheit? The formula is F=(C9/5)+32F = (C * 9/5) + 32.

With these advanced structural patterns, you're now equipped to build more robust, maintainable, and professional AI applications in Python.