Skip to content

NAM102: a property named like a command

Junior

A property is read like an attribute, with no parentheses: node.parent, file.size. Its name should say what it holds, so it should be a noun. A verb at the start of the name reads like an action that never happens.

class Node:
    @property
    def get_child(self):  # NAM102: reads as an action
        return self._children[0]

    @property
    def first_child(self):  # names what it holds
        return self._children[0]

To fix it, either rename the property after what it returns, or drop @property and keep it a method, which callers then call with parentheses.

Senior

At the call site, node.get_child looks like a bound method that someone forgot to call. A reviewer either adds the parentheses, which raises a TypeError, or stops to read the class. Both cost more than a better name.

Whether a word is a verb comes from a word list built from real English text, never from a list someone wrote by hand. Only words used as a verb at least 90% of the time count, so name, value, handle and drive, which are often nouns, stay quiet. A word the list doesn't know, such as parse or compute, is also silence.

Expect some noun phrases that open with a verb-like word: verify_mode is a mode and include_dir is a directory. These are correct, and they belong in the allowlist:

[tool.namelint.allow]
NAM102 = ["verify_mode", "Config.include_dir"]

Expert

The verb table is data/verb_pos.json, built by tools/build_verb_table.py from the UD English-EWT and GUM treebanks (release 2.14). For each word form it counts how often the form is tagged as a verb base form (VB) or a non-third-person present (VBP) against its other tags. verbs.py keeps the forms at or above THRESHOLD = 0.9. The table reaches the check through Context.verbs, so checks.py reads no file.

Only the first word of the name is tested, after splitting on _. A private name has an empty first word and never matches. Both @property and @cached_property count.

This check is the noisiest per finding after NAM108. Its corpus rate is low (0.06 per thousand in CPython, 0.84 in pytest), but a good share of what it reports are noun compounds like verify_mode. They are correct English that a part-of-speech tag on one word cannot see. Raising the threshold would drop real verbs before it dropped those compounds, so they go to the allowlist.