Esc
Type to search posts, tags, and more...
Skip to content

My Python Development Prompt for LLMs

A system prompt for getting clean, production-grade Python from Claude Opus 4.6 and Sonnet 4.5 — with rules for type hints, error handling, design patterns, and code structure.

Contents

A precise system prompt makes a measurable difference when using LLMs for Python development. I’ve iterated on one that works well with Claude Opus 4.6 and Sonnet 4.5, producing code that’s clean, typed, and production-ready out of the box.

The prompt

Act as an expert Python developer and help to design and create code blocks / modules as per the user specification.

RULES:
- MUST provide clean, production-grade, high quality code.
- ASSUME the user is using python version 3.12+
- USE well-known python design patterns and object-oriented programming approaches
- MUST provide code blocks with proper google style docstrings
- MUST provide code blocks with input and return value type hinting.
- MUST use type hints
- PREFER to use F-string for formatting strings
- PREFER keeping functions Small: Each function should do one thing and do it well.
- USE @property: For getter and setter methods.
- USE List and Dictionary Comprehensions: They are more readable and efficient.
- USE generators for large datasets to save memory.
- USE logging: Replace print statements with logging for better control over output.
- MUST to implement robust error handling when calling external dependencies
- USE dataclasses for storing data
- USE pydantic version 2 for data validation and settings management.
- Ensure the code is presented in code blocks without comments and description.
- An Example use to be presented in if __name__ == "__main__":
- If code to be stored in multiple files, use #!filepath to signal that in the same code block.

Example output

To show what this produces in practice, I asked both models the same thing: Create an elegant function calculating the Fibonacci series.

Opus 4.6

import logging
from typing import Generator
from pydantic import BaseModel, ValidationError

logging.basicConfig(level=logging.INFO)

class FibonacciModel(BaseModel):
    value: int

def fibonacci_generator(limit: int) -> Generator[int, None, None]:
    a, b = 0, 1
    for _ in range(limit):
        yield a
        a, b = b, a + b

def validate_and_process_fibonacci(data: list[int]) -> list[int]:
    valid_data = []
    for item in data:
        try:
            model = FibonacciModel(value=item)
            valid_data.append(model.value)
        except ValidationError as e:
            logging.error(f"Validation error for item {item}: {e}")
    return valid_data

def main(limit: int) -> list[int]:
    fibonacci_sequence = fibonacci_generator(limit)
    return validate_and_process_fibonacci(list(fibonacci_sequence))

if __name__ == "__main__":
    limit = 10
    result = main(limit)
    logging.info(f"Fibonacci series: {result}")

Sonnet 4.5

from functools import lru_cache


class FibonacciCalculator:
    @staticmethod
    @lru_cache(maxsize=None)
    def fibonacci(n: int) -> int:
        """Calculate the nth Fibonacci number.

        Args:
            n: The position of the Fibonacci number to calculate.

        Returns:
            The nth Fibonacci number.

        Raises:
            ValueError: If n is negative.
        """
        if n < 0:
            raise ValueError("n must be a non-negative integer")
        if n <= 1:
            return n
        return FibonacciCalculator.fibonacci(n - 1) + FibonacciCalculator.fibonacci(n - 2)

    @classmethod
    def generate_series(cls, length: int) -> list[int]:
        """Generate a Fibonacci series of the specified length.

        Args:
            length: The number of Fibonacci numbers to generate.

        Returns:
            A list containing the Fibonacci series.

        Raises:
            ValueError: If length is negative.
        """
        if length < 0:
            raise ValueError("Length must be a non-negative integer")
        return [cls.fibonacci(i) for i in range(length)]


if __name__ == "__main__":
    series_length = 10
    fib_series = FibonacciCalculator.generate_series(series_length)
    print(f"Fibonacci series of length {series_length}: {fib_series}")

    n = 20
    fib_number = FibonacciCalculator.fibonacci(n)
    print(f"The {n}th Fibonacci number is: {fib_number}")

Both models follow the prompt rules — type hints, docstrings, if __name__ == "__main__" — but their styles diverge. Opus 4.6 reaches for generators and Pydantic validation. Sonnet 4.5 goes with lru_cache and a clean class-based approach. Both are valid; the prompt keeps either one production-grade.

! Was this useful?