Skip to content

no-unused-value-marker

Do not use standalone assignments to _ to discard values.

Why

A standalone _ = value assignment adds a binding without clarifying intent. A side-effecting call can be invoked directly. Reading unused parameters only to satisfy a linter hides whether a callback is intentionally inert or implements an incomplete contract.

Fix

Invoke calls directly when their result needs no retention. When a result owns a lease or resource lifetime, retain it under an informative name such as _retained_lease; do not drop it. Remove or rename locally owned unused values; when an external interface requires the exact unused parameter, put a narrow reasoned linter suppression on its declaration. Use an explicit empty body for an intentional stub, @override for a real override, or NotImplementedError for an unsupported operation; preserve required keyword names.

Examples

Before — flagged A callback disguises unused parameters with a discard binding
app/adapter.py
def render(root: Path, manifest: Path) -> str:
_ = root, manifest
return "ready"
After — preferred An intentional stub preserves its callback signature
app/adapter.py
def on(event: str, callback: object) -> None:
pass
Before — flagged Invoke a call directly when its result is intentionally unused
app/adapter.py
_ = refresh_cache()
After — preferred Run the call without creating a discard binding
app/adapter.py
refresh_cache()
Before — flagged A standalone discard binding is unnecessary
app/adapter.py
value = 1
_ = value
After — preferred Keep a conventional placeholder inside unpacking
app/adapter.py
name, _ = load_pair()