On 9/18/20 6:41 PM, Guido van Rossum wrote:
On Fri, Sep 18, 2020 at 6:19 PM Ethan Furman wrote:
So at this point, I think the choices are:
Standard Enum __repr__ __str__ <RegexFlag.IGNORECASE: 2> RegexFlag.IGNORECASE
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 >>>
Well, the `str(re.I) == "RegexFlag.IGNORECASE"` is due to a bug I just fixed a couple days ago. The intent, according to a comment in the issue, was that str() and repr() would return the same thing, "re.IGNORECASE".
I honestly think we've already lost consistency.
I counted roughly 25 Enums in the stdlib at this point, and only two of them have modified reprs or strs; and one of those is an internal class. It's worth noting that two others are buggy -- one is being fancy with values and didn't get the custom __new__ correct, they other left in some commas when converting from it's original data type.
Most of those 25 were created via [Enum|IntEnum]._convert_ .
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(). :-)
We could certainly go that route. The value is readily available, even if not printed by default.
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'.
Thank you for that -- it's an invaluable debugging tool which I have been grateful for many times.
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 >>>
I think that's too terse -- the first bit, whether class or module, repr or str, is very important -- especially if you have several enums using some of the same names for their members.