```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.
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
| Model | Quality | Cost | Latency | Tokens |
|---|---|---|---|---|
| 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
# 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)
]
```
```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.
```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.
Related queries
Try it with a real tool
Run this prompt in one of these tools. Affiliate links help keep Gridlyx free.