[Python-ideas] AMEND PEP-8 TO DISCOURAGE ALL CAPS

Steven D'Aprano steve at pearwood.info
Fri Jan 4 22:41:43 EST 2019


On Fri, Jan 04, 2019 at 01:01:51PM -0600, Abe Dillon wrote:

> I keep coming back to this great video <https://vimeo.com/74316116> about
> coding style, and one point in particular rings true to me:
> ALL_CAPS_IS_OBNOXIOUS
> 
> It destroys the visual flow of code 

Does it? This claim doesn't ring true to me. To me, "visual flow of 
code" is the way it flows down and across the page, not the shape of the 
individual words.

To me, long lines spoil the visual flow of code (especially if they are 
long enough that I have to scroll horizontally to see the end).

To me, sudden blocks of unexpected indentation spoil the visual flow of code. 
(Fortunately, this is rare in Python.)

I've looked over code in the standard library, my own code, and 
third-party libraries, and I don't see that the choice of name disrupts 
the flow of code, whether it is written in CamelCase of lowercase or 
ALLCAPS or even rAnSOmenOTecAse. (Although I admit that last one is 
quite hard to read...)

I have a bunch of code written in RPL for the HP-48GX calculator, and 
the convention there is that nearly everything is written in allcaps. 
Here's an equivalent function to Python's divmod():

    << DUP2 DIV SWAP OVER * ROT SWAP - >>

The flow is fine if you know how to read reverse Polish notation ("Yoda 
speak"). It flows from left to right, and top down, same as English. 
Only the word order is different. The flow would be precisely the same 
if it were written like this:

    << dup2 div swap over * rot swap - >>

Where RPL does suffer from the lack of visual flow is the lack of 
structure to the code. In Python terms, it would be as if we wrote:

    def function(): if condition: for x in sequence: do_this() 
    do_that() endfor else: do_something_else() endif

Ouch.

The bottom line is, I don't agree that the visual flow of code is 
negatively affected, or affected at all, by the shape of individual 
words in the code.


> and for what? To signify a global,
> constant, or Enum? Is that really so important? I don't think so.

I think the convention is useful, of moderate importance, and I think 
Python code would be ever-so-slightly harder to understand without it.

I rarely, if ever, use allcaps for constants defined and used in a 
single function, but that's because my functions are typically short 
enough that you can fit the entire function on screen at once and tell 
that the name is defined once and never re-bound, hence a constant.

Where the naming convention really makes sense is for module-level 
constants, where the initial binding is typically separated from the 
eventual use by a lot of time and space, I think it is useful to have a 
simple naming convention to distinguish between variables and constants. 
When I see this in the middle of a function:

    def foo():
        ...
        process(spam, FILENAME, eggs, ...)
        ...

I can immediately tell that unlike spam and eggs, FILENAME ought to be a 
global constant, which is a valuable hint that I can probably find the 
value of FILENAME by looking at the top of the module, and not worry 
about it being rebound anywhere else. So yes, having a naming convention 
for constants is useful.

And FILENAME is much better than cfilename or kfilename or 
constant_filename_please_dont_rebind_ok_thx *wink*

What naming convention would you suggest for distinguishing between 
constants and variables?

I suppose one might argue that we don't need to care about the semantics 
of which names are variables and which are constants. In fairness, we 
cope quite well with modules, classes and functions being effectively 
constants and yet written in non-allcaps.

But on the other hand, we generally can recognise modules, classes and 
functions by name and usage. We rarely say "process(module)", but we 
might say "process(module.something)". Classes have their own naming 
convention. So the analogy between global constants which don't use the 
allcaps convention (namely modules, classes and functions) and global 
constants which do is fairly weak. We can (usually) accurately 
recognise modules, classes and functions from context, but we can't do 
the same for constants.


> Currently PEP-8 prescribes all caps for constants
> <https://www.python.org/dev/peps/pep-0008/#constants> and uses the all cap
> variable "FILES" as an example in a different section.
> <https://www.python.org/dev/peps/pep-0008/#when-to-use-trailing-commas> It
> also appears to be the defacto-standard for enums (based on the
> documentation <https://docs.python.org/3/library/enum.html#creating-an-enum>
> )

That's because the typical use for enums is as constants. If I had a 
*variable* which merely held an enum, I wouldn't use allcaps:

    # No! Don't do this!
    for MYENUM in list_of_enums:
        if condition(MYENUM):
             MYENUM = something_else()
        process(MYENUM)



-- 
Steve


More information about the Python-ideas mailing list