Why does Pylint object to single-character variable names?

PythonPylintNaming Conventions

Python Problem Overview


I'm still getting used to Python conventions and using Pylint to make my code more Pythonic, but I'm puzzled by the fact that Pylint doesn't like single character variable names. I have a few loops like this:

for x in x_values:
   my_list.append(x)

and when I run pylint, I'm getting Invalid name "x" for type variable (should match [a-z_][a-z0-9_]{2,30} -- that suggests that a valid variable name must be between 3 and 31 characters long, but I've looked through the PEP8 naming conventions and I don't see anything explicit regarding single lower case letters, and I do see a lot of examples that use them.

Is there something I'm missing in PEP8 or is this a standard that is unique to Pylint?

Python Solutions


Solution 1 - Python

A little more detail on what gurney alex noted: you can tell Pylint to make exceptions for variable names which (you pinky swear) are perfectly clear even though less than three characters. Find in or add to your pylintrc file, under the [FORMAT] header:

# Good variable names which should always be accepted, separated by a comma
good-names=i,j,k,ex,Run,_,pk,x,y

Here pk (for the primary key), x, and y are variable names I've added.

Solution 2 - Python

Pylint checks not only PEP8 recommendations. It has also its own recommendations, one of which is that a variable name should be descriptive and not too short.

You can use this to avoid such short names:

my_list.extend(x_values)

Or tweak Pylint's configuration to tell Pylint what variable name are good.

Solution 3 - Python

In strongly typed languages, one-letter name variables can be ok-ish, because you generally get the type next to the name in the declaration of the variable or in the function / method prototype:

bool check_modality(string a, Mode b, OptionList c) {
    ModalityChecker v = build_checker(a, b);
    return v.check_option(c);
}

In Python, you don't get this information, so if you write:

def check_modality(a, b, c):
    v = build_checker(a, b)
    return v.check_option(c)

you're leaving absolutely no clue for the maintenance team as to what the function could be doing, and how it is called, and what it returns. So in Python, you tend to use descriptive names:

def check_modality(name, mode, option_list):
    checker = build_checker(name, mode)
    return checker.check_option(option_list)

And you even add a docstring explaining what the stuff does and what types are expected.

Solution 4 - Python

Nowadays there is also an option to override regexp. I.e., if you want to allow single characters as variables:

pylint --variable-rgx="[a-z0-9_]{1,30}$" <filename>

So, Pylint will match PEP8 and will not bring additional violations on top. Also you can add it to .pylintrc.

Solution 5 - Python

The deeper reason is that you may remember what you intended a, b, c, x, y, and z to mean when you wrote your code, but when others read it, or even when you come back to your code, the code becomes much more readable when you give it a semantic name. We're not writing stuff once on a chalkboard and then erasing it. We're writing code that might stick around for a decade or more, and be read many, many times.

Use semantic names. Semantic names I've used have been like ratio, denominator, obj_generator, path, etc. It may take an extra second or two to type them out, but the time you save trying to figure out what you wrote even half an hour from then is well worth it.

Solution 6 - Python

pylint now has good-names-rgxs, which adds additional regex patterns to allow for variable names.

The difference is that that variable-rgx will override any previous rules, whereas good-names-rgxs adds rules on top of existing rules. That makes it more flexible, because you don't need to worry about breaking previous rules.

Just add this line to pylintrc to allow 1 or 2 length variable names:

good-names-rgxs=^[_a-z][_a-z0-9]?$

^          # starts with
[_a-z]     # 1st character required
[_a-z0-9]? # 2nd character optional
$          # ends with

Solution 7 - Python

The configuration that pylint itself generates will allow i, j, k, ex, Run, though not x,y,z.

The general solution is to adjust your .pylintrc, either for your account ($HOME/.pylintrc) or your project (<project>/.pylintrc).

First install pylint, perhaps inside your .env:

source myenv/bin/activate
pip install pylint

Next run pylint, but the file is too long to maintain manually right from the start, and so save on the side:

pylint --generate-rcfile > ~/.pylintrc--full

Look at the generated ~/.pylintrc--full. One block will say:

[BASIC]

# Good variable names which should always be accepted, separated by a comma.
good-names=i,
           j,
           k,
           ex,
           Run,
           _

Adjust this block as you like (adding x,y,..), along with any other blocks, and copy your selected excerpts into ~/.pylintrc (or <project>/.pylintrc).

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionAmandaView Question on Stackoverflow
Solution 1 - PythonmlncnView Answer on Stackoverflow
Solution 2 - PythonwarvariucView Answer on Stackoverflow
Solution 3 - Pythongurney alexView Answer on Stackoverflow
Solution 4 - PythonJimilianView Answer on Stackoverflow
Solution 5 - PythonRussia Must Remove PutinView Answer on Stackoverflow
Solution 6 - PythonwisbuckyView Answer on Stackoverflow
Solution 7 - PythonSamView Answer on Stackoverflow