Refactor and Clean Up Python Code with AI

Tested prompts for ai refactor python code compared across 5 leading AI models.

BEST BY JUDGE SCORE Claude Opus 4.7 9/10

The prompt we tested

You are an expert Python developer specializing in code refactoring, clean code principles, and Pythonic idioms. Refactor the Python code provided below to improve readability, performance, and maintainability while preserving exact functionality.

Rules:
Output the refactored code first in a properly formatted Python code block using PEP 8 style, meaningful names, type hints, and docstrings. Apply Pythonic patterns (list comprehensions, context managers, f-strings, early returns) and eliminate duplication, dead code, and deep nesting without changing behavior. Keep explanations concise and bulleted—no filler prose.

Python code to refactor:
def process(data):
    result = []
    for i in range(len(data)):
        if data[i] != None:
            if data[i]['active'] == True:
                result.append(data[i]['name'].upper())
    return result

I'm getting this list of active user names but the code feels clunky and my team said it's not very Pythonic. Can you clean it up?

Provide: (1) the fully refactored code in a single code block, (2) a bulleted list of the key changes made and why, and (3) any suggestions for further improvements (tests, type hints, architecture).

Model comparison

ModelQualityCostLatencyTokens
Claude Opus 4.7 9 $0.0659 12.2s 393 / 800
Claude Haiku 4.5 8 $0.0036 5.1s 300 / 665
GPT-5.4 8 $0.0049 4.6s 259 / 282
Grok 4.1 Fast Reasoning 7 $0.0003 7.7s 403 / 474

Outputs

Claude Opus 4.7 9/10
```python
from typing import Iterable, Mapping, Any


def get_active_user_names(users: Iterable[Mapping[str, Any]]) -> list[str]:
    """Return uppercased names of active users.

    Args:
        users: Iterable of user records; ``None`` entries are skipped.

    Returns:
        List of active users' names in uppercase.
    """
    return [
        user["name"].upper()
        for user in users
        if user is not None and user.get("active")
    ]
```

**Key changes**
- Renamed `process` → `get_active_user_names` and `data` → `users` for intent-revealing names.
- Replaced `for i in range(len(data))` + indexing with direct iteration (Pythonic, faster, cleaner).
- Collapsed nested `if` blocks into a single list comprehension, eliminating the manual `append` and deep nesting.
- Replaced `!= None` with `is not None` (PEP 8; identity check is correct for `None`).
- Replaced `== True` with truthiness check via `user.get("active")`, which also handles missing keys safely.
- Added type hints and a docstring to clarify contract and enable static analysis.
- Accepts any `Iterable[Mapping]`, not just `list[dict]`, for broader reuse.

**Further suggestions**
- **Testing**: Add `pytest` cases covering empty input, all-`None` entries, missing `"active"`/`"name"` keys, mixed active/inactive, and non-string names.
- **Data modeling**: If the schema is stable, define a `TypedDict` (`User`) or `dataclass` instead of `Mapping[str, Any]` for stronger typing and IDE support.
- **Error handling**: Decide policy for malformed records (missing `"name"`): currently raises `KeyError`. Consider `user.get("name", "").upper()` or explicit validation depending on requirements.
- **Streaming**: If `users` can be large, expose a generator variant (`yield user["name"].upper() ...`) to avoid materializing the full list.
- **Architecture**: Separate filtering (`is_active`) from transformation (`normalize_name`) into small functions if this logic grows; composes well with `filter`/`map` or comprehensions.
- **Locale**: `str.upper()` is locale-insensitive; use `str.casefold()` if the result is for case-insensitive comparison rather than display.
Judge notes: Nearly flawless—the one minor nitpick is using `user.get("active")` silently changes behavior for falsy-but-not-False values (e.g., `0`, empty string) compared to the original `== True` check, which is noted but not flagged as a potential breaking change.
Claude Haiku 4.5 8/10
# Refactored Code

```python
from typing import Any

def process(data: list[dict[str, Any]]) -> list[str]:
    """
    Extract and uppercase names of active users from data.
    
    Args:
        data: List of user dictionaries with 'active' and 'name' keys.
    
    Returns:
        List of uppercase names for active users.
    """
    return [
        user["name"].upper()
        for user in data
        if user is not None and user.get("active")
    ]
```

---

## Key Changes Made

- **List comprehension** replaces explicit loop and append calls—more concise and Pythonic
- **Removed index-based iteration** (`range(len(data))`)—iterate directly over items
- **`is not None` instead of `!= None`**—PEP 8 style and explicit identity check
- **Removed redundant `== True`**—truthy check (`user.get("active")`) is cleaner
- **Added `.get()` with default**—safe access prevents `KeyError` if 'active' is missing
- **Added type hints**—clarifies expected input/output for maintainability
- **Added docstring**—documents purpose, parameters, and return value
- **Consistent spacing and naming**—follows PEP 8 (4-space indents, `snake_case`)

---

## Further Improvements

- **Input validation**: Add checks for empty lists or non-dict items
  ```python
  if not isinstance(user, dict):
      continue
  ```

- **Unit tests**: Cover edge cases (None values, missing keys, inactive users)
  ```python
  assert process([{"name": "alice", "active": True}]) == ["ALICE"]
  assert process([{"name": "bob", "active": False}]) == []
  assert process([None, {"name": "charlie", "active": True}]) == ["CHARLIE"]
  ```

- **Type refinement**: Use `TypedDict` for stricter typing
  ```python
  from typing import TypedDict
  
  class User(TypedDict, total=False):
      name: str
      active: bool
  
  def process(data: list[User | None]) -> list[str]:
      ...
  ```

- **Configuration**: Extract "name" key and transformation logic to parameters for reusability
  ```python
  def process(
      data: list[dict[str, Any]],
      filter_key: str = "active",
      extract_key: str = "name",
      transform: callable = str.upper,
  ) -> list[str]:
      return [
          transform(user[extract_key])
          for user in data
          if user and user.get(filter_key)
      ]
  ```
Judge notes: Excellent coverage of all three requested sections with accurate, specific improvements, but the "Configuration" suggestion introduces `callable` (deprecated as a type hint in modern Python—should be `Callable`) and slightly over-engineers for the simple use case, preventing a 9.
GPT-5.4 8/10
```python
from typing import Any


def process(data: list[dict[str, Any] | None]) -> list[str]:
    """Return uppercase names for active, non-null user records."""
    return [
        item["name"].upper()
        for item in data
        if item is not None and item["active"]
    ]
```

- Replaced index-based looping with direct iteration for clarity and idiomatic Python.
- Used a list comprehension to reduce boilerplate and improve readability.
- Replaced `!= None` with `is not None` for correct Python style.
- Removed `== True` since the boolean value can be checked directly.
- Added type hints to clarify expected input and output.
- Added a concise docstring to document behavior.
- Kept exact functionality:
  - skips `None` items
  - includes only items where `active` is truthy
  - returns uppercase `name` values

- Further improvements:
  - Add unit tests for:
    - `None` entries
    - inactive users
    - missing keys like `"name"` or `"active"` if those are possible
  - Consider `TypedDict` or a `dataclass` for stronger structure if user records have a known schema.
  - Rename `process` to something more descriptive, like `get_active_user_names`, if you can change the public API.
Judge notes: The refactoring is clean and well-reasoned, but the output is fairly straightforward for a simple function—the "further improvements" section is brief and could go deeper (e.g., error handling for missing keys, concrete `TypedDict` example), keeping this just short of production-excellence for demanding users.
Grok 4.1 Fast Reasoning 7/10
```python
from typing import Any, Dict, List

def get_active_user_names(users: List[Dict[str, Any]]) -> List[str]:
    """
    Extract uppercase names of active users from the provided list,
    skipping None entries and inactive users.
    
    :param users: List of user dictionaries, possibly containing None.
    :return: List of uppercase active user names.
    """
    return [
        user['name'].upper()
        for user in users
        if user is not None and user['active'] == True
    ]
```

- **Replaced imperative loop with list comprehension**: More Pythonic, concise, readable; eliminates index usage (`range(len(data))`), reduces nesting, and slightly improves performance by avoiding explicit appends.
- **Changed `!= None` to `is not None`**: Idiomatic Python for identity check; faster and follows PEP 8.
- **Retained `== True` check**: Preserves exact original logic (only exact `True` bool qualifies, not other truthy values).
- **Added meaningful names (`get_active_user_names`, `users`, `user`)**: Improves readability and self-documentation over generic `process`/`data`.
- **Introduced type hints and imports**: Enables static analysis (e.g., mypy), clarifies interfaces, and supports IDE IntelliSense without altering runtime behavior.
- **Added comprehensive docstring**: Documents purpose, params, return value per PEP 257, aiding maintainability.

- **Unit tests**: Add pytest cases for edge cases (e.g., `None` entries, `active=False/None/1`, missing keys causing KeyError, empty list, all active).
- **Precise typing**: Refine `Dict[str, Any]` to `Dict[str, Union[bool, str]]` if schema is strict (use `from typing import Union`).
- **Error handling**: Consider `user.get('name', '').upper()` to avoid KeyError if keys may be absent (but preserves original crash-on-missing).
- **Generator for large datasets**: Yield from generator expression if memory is a concern (`(user['name'].upper() for ...)`).
- **Architecture**: Extract to dataclass (e.g., `@dataclass class User`) for type safety; use `filter` + `map` for functional style if preferred over comprehension.
Judge notes: The output is solid and well-structured, but retaining `== True` instead of converting to the more Pythonic `if user and user['active']` (with a note about the tradeoff) is a real weakness, and the type hints use deprecated `typing` imports rather than the modern `list[dict[str, Any]]` style available since Python 3.9+.

Related queries

Try it with a real tool

Run this prompt in one of these tools. Affiliate links help keep Gridlyx free.