I am a Python programmer primarily who uses pylint for linting source code. I am able to eliminate all of the warnings except one: Invalid name for a constant. Changing the name to all caps fixes it, but am I really supposed to do that? If I do it, I find that my code looks ugly as most of the variables are constant (according to pylint).
5 Answers
You are probably writing code like this:
notes_director = argv[1]
chdir(notes_director)
files = glob('*.txt')
rand_file = choice(files)
with open(rand_file) as notes_file:
points = notes_file.readlines()
rand_point = choice(points)
You should move this code into a function:
def main():
notes_director = argv[1]
chdir(notes_director)
files = glob('*.txt')
rand_file = choice(files)
with open(rand_file) as notes_file:
points = notes_file.readlines()
rand_point = choice(points)
# actually call the main function
main()
Pylint assumes that code that actually does the work will be inside a function. Because you have this code at the top level of your code instead of inside a function it gets confused.
Generally speaking, it is better style to do work inside a function instead of at the top level. This allows you to better organize what you are doing and facilitates reusing it. You should really only have code performing an algorithm outside of a function in a quick and dirty script.
-
8Strongly disagree, I think there are many good Pythonic reasons to use module level variables. I think this advice is merely an artifact of pylint misreading PEP8, and assuming the converse of "constants should be module level" should also be true. May 21, 2019 at 21:58
-
2There are many good reasons to use variables at a module level, but most of those reasons are you want a constant, or if it isn't a constant it will probably only be set once. If it's all over the code as OP states then it's probably being misused. I can't think of any code I've ever seen that had more module level variables than function scope level variables. Jan 10, 2020 at 3:36
-
1@Turksarama: small scripts often don't have much function level variables, if they have any functions at all.– Lie RyanJan 11, 2020 at 4:13
-
1That's true enough, but for a script that small I'm not likely to care about getting rid of all my PEP8 warnings either. Jan 11, 2020 at 10:36
-
Overall point: pylint shouting should make you think. Even if the thought may be pylint is wrong. And above example is indeed one where you should rethink your coding style. mission accomplished. Jul 18, 2022 at 15:48
Yes. According to PEP8s rule on constants:
Constants are usually defined on a module level and written in all capital letters with underscores separating words. Examples include
MAX_OVERFLOW
andTOTAL
.
Long Version:
In the Python community (as in many other communities) exist conventions about how to write code. This is different from working code: even if you write your constants all lowercase, your code still works.
But there is community consensus (as documented in PEP8) which is "enforced" with tools like pylint. If you program for your own happiness, you may neglect the hints pylint gives you. If you want open exchange with the community, aka »someone besides myself should use my code«, you should prepare your code according to PEP8.
-
10On the other hand, it's entirely possible for
pylint
to get it wrong. Python doesn't provide a way of distinguishing a constant from a variable, other than that the constant is expected to always have the same value.pylint
assumes that anything that is only set once and doesn't ever change is a constant, but unless it's intended to be a constant, that could just be an artifact of the implementation. And specifically the code given in the comment to the question has values that will be different on each run, therefore should not be considered constants even if pylint thinks they are.– JulesMar 21, 2018 at 8:46 -
@Jules I would call variables set once and changing during runtime never again a constant, hence exists in many languages (e.g. in JS) a
const
keyword. Although the initial value is different, other than maybePI
. Aug 8, 2018 at 7:27 -
3I'd distinguish between an immutable variable (i.e. something that's set at runtime and not changed) and a constant (i.e. something that is the same in every program run, and if the language provides the option to do it could be computed at compile time) ... the point is that because there's a lack of any way of specifying the distinction to python,
pylint
assumes the latter even when the former is the case.– JulesAug 8, 2018 at 8:02 -
Pylint is definitely in the wrong, in that it read "constants should be module level" and assumed the converse "module level should be constants". But because it's otherwise a good, useful tool seems we're getting stuck with it. May 21, 2019 at 21:57
-
1@MetricSystem The point for me to (mostly) avoid mutable globals is simple: reducing complexity. On the one hand you might argue, it might be easier to modify, so it reduces complexity where the variable is used and modified. OTOH: understanding what mutates the state becomes really hard. It may work for projects, like it does work for you to cross the street without traffic checking: The only problem is, when you have to explain, why you were hit by a car. But, perhaps it doesn't happen. May 23, 2019 at 7:19
The PEP8 and Python community norm is to use ALL_CAPS_CONSTANTS
. It's a common visual clue, used for decades in C, Java, Perl, PHP, Python, bash, and other programming languages and shell environments. But in modern online parlance, ALL CAPS SIGNIFIES SHOUTING. And shouting is rude.
Python is, however, rather inconsistent about ALL_CAPS_CONSTANTS
. JavaScript may have Math.PI
, but Python has math.pi
. There's no more recognizable or enduring constant than π. Or consider sys.version_info
, the version of Python you're running on. 100% constant over the life of your program--far more than PORT
or MAX_ITERATIONS
or other constants you'd define. Or how about sys.maxsize
? Your platform's maximum native integer value is constant over not just one or two program runs, but the life of your hardware.
If these constants--including some like π and e that are fundamental constants of the universe, and will not vary over all eternity--if they can be lower-case, well...so can other constants. You can choose.
Remember, PEP8 is a style guide. A guideline, not a law. A guideline often contravened even by Python's standard library. And citing another core Python guideline, PEP20 (aka "The Zen of Python"):
- Beautiful is better than ugly
- Readability counts
- Practicality beats purity.
On a practical note, when a program's YELLY_CONSTANT
and SHOUTY_PARAMETER
starts to grate, it helps to remember that the all-caps constants generally are not really enduring Platonic ideals, but parameters of a program run. There is nothing truly constant about PORT
, SITENAME
, or NUMRUNS
, and they don't have to be managed as standalone program globals. For example, they can be dropped into a dictionary as a globally-accessible bundle of program parameters:
config = {
'port': 80,
'sitename': "Bubba's Blog",
'numruns': 100,
}
Python also has a fine keyword parameter passing facility that reduces the need to use APPARENTLY_ANGRY_GLOBAL_VARIABLES
:
def process_data(sitename, port=80, numruns=100):
...
process_data("Bubba's Blog")
In practice, many of these values will be (or should be) read from config files, OS environment variables, command line arguments, or other sources to satisfy the inversion of control principle/pattern. But that's a larger story for another day.
-
3Upvoted because of the humor in this answer. But do note that "in modern parlance" it's highly inconsistent whether people consider all caps shouty or not -- I find there's a 50/50 chance any given person will use caps without meaning to shout. Programmers of a certain age tends to understand this better, because -- I now contend -- it's not "modern parlance" but "old internet custom", and people nowadays are less aware of it :) Jan 10, 2020 at 14:50
Yes, it's quite common in most programming language (at least those I use).
You can refer to this Google link to share a common style between developers of the same team.
It's advised to use
Type |Public |Internal
Global/Class Constants|CAPS_WITH_UNDER |_CAPS_WITH_UNDER
The code will work regardless of whether you capitalise constants. These so-called "constants" are just variables that won't change during the code execution.
My personal opinion is that if they are capitalised it is easier to remember they are supposed to be constants.
import operator
OPERATIONS = {"+": operator.add, "-": operator.sub}
def check_answer(num_1, num_2, operation, user_answer):
correct_answer = OPERATIONS.get(operation)(num_1, num_2)
is_correct = user_answer == correct_answer
return (is_correct, correct_answer)
Also, PEP8 says that you should use capitals.
-
Thanks for linking to the official style guide. I'd leave out the "this is what I usually do" part, that's not well reasoned advice for others :)– Martin KJan 9, 2020 at 20:42
-
NOTES_DIRECTORY = argv[1] chdir(NOTES_DIRECTORY) FILES = glob('*.txt') RAND_FILE = choice(FILES) with open(RAND_FILE) as notes_file: POINTS = notes_file.readlines() RAND_POINT = choice(POINTS)