On Fri, Sep 18, 2020 at 6:19 PM Ethan Furman <ethan@stoneleaf.us> wrote:
On 9/18/20 3:12 PM, Guido van Rossum wrote:
 > On 9/18/20 2:44 PM, Ethan Furman wrote:

 >> I'm looking for arguments relating to:
 >>
 >> - should _convert_ make the default __repr__ be
 >>   module_name.member_name?
 >
 > I actually like the status quo for regular enums, when repr() shows
 > the type, name and value, and str() shows "classname.flagname", so I'd
 > stick to that for converted flags. Even though this violates the rule
 > of thumb that repr() should look like a valid expression -- perhaps a
 > stronger rule of thumb is that repr() should show more than str().

Well, if the repr is re.IGNORECASE and the str is 2, then we've met that
bar.  ;-)

 >> - should _convert_ make the default __str__ be the same, or be the
 >>   numeric value?
 >
 > Showing just (the str of) the value seems unkind, since e.g. showing
 > '4' makes me think it's just an int. (Then again I can see that for
 > *converted* flags that's not unreasonable.)
 >
 > But yeah, backwards compatibility. However, I don't think we got any
 > complaints about the `re` flags, did we?

The only complaints I'm aware of were before the re constants became an
Enum, but my social media activity consists almost entirely of
Stackoverflow.

:-)

So at this point, I think the choices are:

Standard Enum
       __repr__                   __str__
<RegexFlag.IGNORECASE: 2>   RegexFlag.IGNORECASE

and

Modified Converted Constant
       __repr__                   __str__
re.IGNORECASE                       2


I will admit I fancy the MCC variant more, but we should make a choice
and then be consistent.

Hm, there's also what re actually does (tried in 3.8, 3.9 and 3.10):
```
>>> import re
>>> print(str(re.I))
RegexFlag.IGNORECASE
>>> print(repr(re.I))
re.IGNORECASE
>>>
```
I honestly think we've already lost consistency.

Possibly regular enums (Enum, IntEnum, IntFlag) should just all return "class.name", e.g. 'Color.RED', for both str() and repr(), and "converted" enums should return "module.name", e.g. 're.IGNORE' for both? It restores the rule of thumb, and it's not unusual. Maybe it's a new trend -- PEP 585's list[int] returns "list[int]" for both str() and repr(). :-)

At the same time it's as old as Python -- for most builtins other than strings, repr() and str() are the same, and modeled after repr(). Historically, I only introduced the difference between str() and repr() because of strings -- I wanted the REPL to clearly show the difference between the number 42 and the string '42', but at the same time I wanted both to print as just '42'. Of course numpy took a different fork in that road...

Another brainstorm (or brainfart): maybe repr() should show the module/class and the name, and str() should only show the name. We'd then get
```
>>> # Mock-up!
>>> print(str(re.i))
IGNORE
>>> print(repr(re.i))
re.IGNORE
>>>
```
and similar for Color.RED:
```
>>> # Another mock-up!
>>> print(str(Color.RED))
RED
>>> print(repr(Color.RED))
Color.RED
>>>
```

--
--Guido van Rossum (python.org/~guido)