On Tue, May 25, 2021 at 9:36 PM Steven D'Aprano <steve@pearwood.info> wrote:
> ALLCAPS means "this value should only be set once and not changed."

`math.pi` says hello.

(U ⇒ O) ⊬ (¬U ⇒ ¬O)

The existence of math.pi and the fact that probably nobody ever has
introduced a bug into their code by carelessly assigning another value
to it suggests strongly that the benefit of language enforced constants
is not high.

Well, rarely.  I've once or twice carelessly tested or taught some iterative algorithm for generating pi and made the error of overwriting the name.

In this particular example, and also math.e and math.tau, the lowercase follows external conventions.  From time to time other such mathy constants too.  But the UPPERCASE constants are pretty darn common, pre-dating Python.
 
> _underscore means "this is not part of public API, and it may change in next version.

Namedtuple and the sys module also say hello.

Yeah. There are a few exceptions.

I'll note... perhaps *confess*... that even though I was literally sitting at the desk next to Raymond when he was thinking about the design of namedtuple, and even discussed it with him slightly, I had assumed for more years than I wish to mention that ._asdict and ._fields were not strictly promised because of their names.
 
> __double_under means "this is SERIOUSLY not something you should muck with,
> it's likely to break stuff if you do."

That's a convention I've never heard of before. What's the difference
between "private" and "SERIOUSLY private, I REALLY mean it"?

In classes, it's name mangling.  I've found that most people, or most code I've seen, treat module or function level `__double` names as implicitly similar.  That's certainly what I do myself.  If I don't want someone to rely on a name in future versions of some module, I'll use the single underscore.  If I want to warn them that relying on it might cause bad things even right now, in this version, I'll use the double leading-underscore.

Obviously it's not enforced at a language level. But it's a pretty good clue for other users.
 
The problem with naming conventions is that not everyone knows the
conventions. Not every Python programmer spends hours every day on
Python forums, reading Stackoverflow, etc. What you call "a B&D language
like Java", other people might call "safety rails and warning lights".

It seems like a documentation question then. PEP 8 describes it as:
  • __double_leading_underscore: when naming a class attribute, invokes name mangling

  • __double_leading_and_trailing_underscore__: "magic" objects or attributes that live in user-controlled namespaces. E.g. __init__, __import__ or __file__. Never invent such names; only use them as documented.

  • It's not 100% explicit about double underscore meaning "I REALLY mean it" ... but it's kinda implied in the contrast with single underscore.

    --
    The dead increasingly dominate and strangle both the living and the
    not-yet born.  Vampiric capital and undead corporate persons abuse
    the lives and control the thoughts of homo faber. Ideas, once born,
    become abortifacients against new conceptions.