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

Steven D'Aprano steve at pearwood.info
Wed Jan 30 20:24:07 EST 2019


On Wed, Jan 30, 2019 at 01:47:56PM -0600, Abe Dillon wrote:
> > Is it that really obnoxious?
> 
> EXTREMELY!

I don't agree with you that the use of one or two words in a sentence 
for EMPHASIS is obnoxious, and I don't writing a one-word sentence is a 
good test of that.

In any case, even if it is the case that all-caps has the downside that 
it draws the eye ("shouty") more than necessary, I believe that the 
benefits of the convention outweigh that cost.


> >  Does using upper case for constants measurably slows down coders? Can
> you cite the actual papers describing such experiments that lead to this
> conclusion ?
> 
> https://www.mity.com.au/blog/writing-readable-content-and-why-all-caps-is-so-hard-to-read
> https://en.wikipedia.org/wiki/All_caps#Readability
> https://uxmovement.com/content/all-caps-hard-for-users-to-read/
> https://practicaltypography.com/all-caps.html

None of those "cite the actual papers" as requested, and only the 
Wikipedia page cites secondary sources.

But that's okay, since we don't dispute that wall-to-wall paragraphs of 
all-caps are hard to read, we only dispute that the judicious and 
occasional use of all-caps to communicate metadata about what would 
otherwise appear to be a variable hurts readability in any meaningful 
sense.

It isn't very interesting to say that it takes the average programmer 
(let's say) 250ms to read this line:

    with open(filename, 'w') as f:

versus (let's say) 280ms to read this one:

    with open(FILENAME, 'w') as f:


I don't know if that is true or not, but even if it is, I'm not 
particularly interested in optimizing the time it takes to read 
individual words. When it comes to coding, the time used scanning over a 
line of text is typically insiginificant compared to the time needed to 
understand the semantics and context.

It isn't that I particularly want to slow down reading of indivudual 
words, but I'm willing to lose (let's say) 10 to 20 milliseconds to read 
FILENAME versus filename, so that I don't have to spend (let's say) 30 
to 120 seconds trying to determine whether or not the value of filename 
has been rebound somewhere I didn't expect and that's why my script is 
writing to the wrong file.


> > from my experience having a visual clue that a value is a constant or an
> enum is something pretty useful.
> 
> Do you have any proof that it's useful?

Not peer-reviewed, no, but from my own experience I know that generally 
speaking when I'm trying to understand the semantics of unfamiliar code 
(even if that is code I wrote myself!) if I see an ALLCAPS name, I 
generally know that on a first pass I can treat it as a given and ignore 
it without caring about its actual value.

There are exceptions: for example, if there's a bug in my regex, then I 
do have to care about the value of PATTERN. If I'm writing to the wrong 
file, then I do have to care about the name of FILENAME.

But even then, I can guess that the value is only set in one place. If 
there's a bug in my regex PATTERN, I can fix it once at the top of the 
module, and not worry about other parts of the script or library 
re-binding the value.

> Have you ever been tempted to
> modify math.pi or math.e simply because they're lower case? Have you ever
> stopped to wonder if those values change?

This is a bit of a red herring (but only a bit) because the major value 
for signalling constantness is not so much as a warning to the *writer* 
not to change them, but to the *reader* that in well-written code, they 
haven't been changed.

Obviously you can't have the second without the first, but since code is 
read more than it is written, the second occurs much more often.

When it comes to math.pi and math.e, why would you want to change 
them? What is your use-case for changing them?

I actually do have one. Many years ago, I wondered whether changing 
math.pi would change how math.sin, cos and tan work. So I tried this:

py> import math
py> math.cos(2*math.pi)  # Period of cosine is 2π.
1.0
py> math.pi = 3  # Change the universe! π is now three exactly.
py> math.cos(2*math.pi)  # Should still be 1, right?
0.960170286650366

I learned that the trig functions don't work that way. Ever since then, 
I've never had any reason to want to change the value of math.pi. What 
would be the point?


> If the socket library used packet_host, packet_broadcast, etc. instead of
> PACKET_HOST, PACKET_BROADCAST, ETC. would you be confused about whether
> it's a good idea to rebind those variables?

If they are variables, then by definition they must vary. If they vary, 
there must be reasons to rebind them. Since these are not flagged as 
"private" with a leading underscore, presumably they are part of the 
public API, so I would expect that, yes, rebinding those variables was a 
good idea.

Since I'm not a domain expert when it comes to sockets, I would probably 
spend many minutes, maybe hours, trying to work out what part of the 
socket API requires me to set these global variables, and why.

But in reality, since they are clearly flagged as constants, I can 
assume that they are intended as read-only constants, not global 
variables. I don't need to be a domain expert on sockets to know that 
rebinding PACKET_HOST is a bad idea, I just need to know that it isn't 
supported by the socket module.

(The danger in asking rhetorical questions is that sometimes the answer 
isn't the one you expected.)


> It seems to me that nobody is actually considering what I'm actually
> talking about very carefully. They just assume that because all caps is
> used to convey information that information is actually important.

Or maybe some of us have thought carefully about what you have said, and 
concluded that you are making an unjustified micro-optimization for 
reading time as measured by eye-tracking time over individual words, at 
the cost of total editing and debugging time.


> Not just
> important, but important enough that it should be in PEP-8. They say I
> should just violate PEP-8 because it's not strictly enforced. It is
> strictly enforced in workplaces.

Clearly it isn't "strictly enforced". Because the single most important 
rule of PEP 8 is the one mentioned right at the start about knowing when 
to break all the other rules.

If your workplace forbids any exceptions to the other PEP 8 rules, then 
they are violating the most important PEP 8 rule of all.


> > Surely, I'd hate reading a newspaper article where the editor generously
> sprinkled upper case words everywhere
> 
> Exactly. If it's an eye-sore in every other medium, then it seems likely to
> me, the only reason programmers don't consider it an eye-sore is they've
> become inured to it.

It isn't an eyesore in every other context.

You are making a logical error in assuming that since 
wall-to-wall all-caps significantly hurt readability, so much 
individual all-caps words. This is simply not correct.

    Drinking six litres of water in a single sitting will 
    likely kill an adult; therefore (according to your 
    reasoning) we shouldn't drink even a single sip of water.

https://www.medicaldaily.com/taste-death-ld50-3-popular-drinks-can-kill-you-298918

Even if eye-tracking experiments show that it takes a fraction of a 
second longer to read that one word, that doesn't correspond to "hurting 
readability" in any meaningful sense.

Optimizing for eye-tracking time for its own sake is not a useful thing 
for programmers to worry about.


> > but analogies only go so far, reading code have some similarities with
> reading prose, but still is not the same activity.
> 
> CAN you articulate what is DIFFERENT about READING code that makes the ALL
> CAPS STYLE less offensive?

You are misusing the word "offensive" there. Please don't use it to mean 
"hard to read" or "annoying".

Again, to answer your rhetorical question in a way you probably hoped it 
wouldn't be answered: because we don't write wall-to-wall all-caps code 
(at least not in Python). We're not likely to have six all-caps names in 
a single expression; we're probably not likely to have six all-caps 
names in an entire function.

Consequently the cost of reading the all-caps word is tiny, and the 
benefit is greater.

Just as it is for using all-caps for initialisms and acronyms like AFL, 
USA, FAQs, LD50, LED, PRC, PC, etc. Or for the occasional use for 
emphasis. Etc.



-- 
Steve


More information about the Python-ideas mailing list