NAM104: a command that returns a value¶
Junior¶
A name that starts with a command verb, such as set_, reset_, clear_, update_ or save_, says the function does something. Callers expect nothing back, so they don't look at what it returns.
def set_width(lines, width): # NAM104: returns a new list
return [line[:width] for line in lines]
def truncated(lines, width): # says it returns something
return [line[:width] for line in lines]
If the function returns a value its callers need, rename it after that value. If the value is never used, stop returning it.
Senior¶
list.append, dict.clear and set.add return None, and Python programmers learn early that a command answers nothing. A command that returns a value leads to one of two bugs. The value is dropped by a caller who trusted the name, or a reader assumes the call changed something in place when it built a copy.
These returns stay quiet, because they are protocols and return no computed value:
return Noneas an early exit.return self, for chaining.return Trueorreturn False, reporting success.return super().set_cookie(...), passing on the same command.
A function that returns the old value, like set_verbosity returning the previous level, is a real case. Either name it for the swap (swap_verbosity), or make it a context manager that restores the old value.
Expect to allowlist the copy-and-update idiom, where options.update_width(80) returns a changed copy on purpose. Also expect words that aren't verbs in a given name: close_to_zero is an adjective, and set_validator validates sets.
Expert¶
The command verbs are set, reset, clear, close, print, emit, insert, append, show, stop, warn, init, update and save. Each is in the list because the corpus shows it to be one-sided: reset_ returns nothing in 56 of 59 public functions. Verbs that go both ways (load_, create_, make_, read_, add_, run_, handle_) are in neither list. The verb is the first word of the name. A bare one-word name like close is skipped, since its contract lives in its type (file.close).
Every return in the function's own body is examined, nested functions excluded. The first one that is not a protocol return is the evidence, unparsed and cut at 40 characters. Generators are skipped.
The corpus rate is 0.68 per thousand in CPython. rich stands out at 6.49, almost all from its ConsoleOptions.update_* methods, which return copies by design. That is the idiom the allowlist exists for.