[Python-ideas] Enums

Guido van Rossum guido at python.org
Fri Jul 29 19:56:50 CEST 2011


On Fri, Jul 29, 2011 at 10:40 AM, M.-A. Lemburg <mal at egenix.com> wrote:
> M.-A. Lemburg wrote:
>> Guido van Rossum wrote:
>>> On Fri, Jul 29, 2011 at 7:55 AM, Nick Coghlan <ncoghlan at gmail.com> wrote:
>>>> On Fri, Jul 29, 2011 at 7:37 PM, M.-A. Lemburg <mal at egenix.com> wrote:
>>>>> Paul Colomiets wrote:
>>>>>> The problem with named value is that:
>>>>>>
>>>>>>     namedvalue(1, "red")
>>>>>>
>>>>>> Will give you are repr of "red". And you don't know whether it's
>>>>>> TerminalColors.red or WebSafe.red or BuildbotState.red. And
>>>>>> most of us will be too lazy to add group name or module name
>>>>>> directly into the named value (partially because it's repeating
>>>>>> yourself).
>>>>>>
>>>>>> So the big feature of flufl.enum is classname (call it group
>>>>>> name) in repr and isinstance check.
>>>>>
>>>>> A meta class variant could easily add class and module
>>>>> names to the attrbute name, if needed/wanted.
>>>>
>>>> Given that the status quo is for "TerminalColors.red" et al to just
>>>> display as "1" (or whatever integers they're assigned), I'm finding it
>>>> hard to consider this a particularly significant criticism. If we
>>>> don't even know what *kind* of values are being passed to a debugging
>>>> message, we have bigger problems than whether or not those values have
>>>> been given names (and searching for all named values of 'red' with a
>>>> value of '1' is going to create a much smaller resulting set than
>>>> searching for all values of '1' ).
>>>>
>>>>> Just to make sure:
>>>>>
>>>>> namedvalue() will just change the repr() of the value, not
>>>>> the str() of it, right ?
>>>>
>>>> Yeah, I figured out the mechanics needed to make that work properly
>>>> when writing up the recipe for the cookbook
>>>> (http://code.activestate.com/recipes/577810-named-values/)
>>>>
>>>>> I think that's essential for making namedvalue()s useful
>>>>> in practice, since you mostly need this for debugging
>>>>> and error reporting and don't want the namevalue aspect
>>>>> of a constant to get in the way of its normal use in
>>>>> e.g. conversion to text formats such as JSON, XML, etc.
>>>>
>>>> Yeah, the case I first thought of was writing numbers to CSV files,
>>>> but it's really any data export operation.
>>>
>>> That's assuming the data export format doesn't support enums.
>>>
>>> I would fine enums whose str() is just an int pretty annoying. Note
>>> that str(True) == repr(True) == 'True' and that's how I'd like it to
>>> be for enums in general. If you want the int value, use int(e). If you
>>> want the class name, use e.__class__.__name__ (maybe e.__class__ is
>>> what you're after anyway). My observation is that most enums have
>>> sufficiently unique names that during a debugging session the class is
>>> not a big mystery; it's the mapping from value to name that's hard to
>>> memorize. As a compromise, I could live with str(e) == 'red' and
>>> repr(e) == 'Color.red'. But I don't think I could stomach str(e) == 1.
>>
>> The situation with enums is different than for booleans: many
>> data interchange formats out there support true/false directly,
>> so there's little to change and little breakage involved.
>> And it's easy to fix, since you only to deal with two such
>> enums.
>>
>> However, when you change existing code constants to enums,
>> chances are high that your interchange libraries are going
>> to fail because of this, or your application will start
>> providing broken data to external resources, without you
>> knowing.
>>
>> Since it's easy to switch from %s to %r, if needed, I don't
>> see much of a problem with having str(e) continue to return
>> the integer string.
>>
>> Regarding the repr(e): This should really be user-defined.
>> There situations where you want to see both the integer
>> code and description in the repr(e), e.g. when dealing with
>> error codes where you quickly need to communicate the
>> error, so a format like '[123] Error contacting server'
>> would be better than just 'Error contacting server'.
>>
>> In other cases, the subsystem is important, so getting
>> '[Server][FTP] Permission error' is more useful than
>> just 'Permission error'.
>>
>> And in yet other circumstances, you want to see the
>> defining module and class.
>
> Thinking about this some more: it would be good
> to have attributes
>
>  .name - namedvalue name
>  .value - namedvalue value object
>
> on enums and have str(e) == str(e.value) and
> repr(e) == e.name.
>
> BTW: Would it be possible to have work for more than just
> integers ? If not, "namedint" may be a more intuitive name.

Nick's proposal for named values is to work for any type. But I think
that the things called enums ought to be an int subclass. I guess if
enums are named values their value attribute should return a plain int
with the same value.

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



More information about the Python-ideas mailing list