[Python-ideas] PEP for enum library type?

Steven D'Aprano steve at pearwood.info
Tue Feb 12 23:51:50 CET 2013


On 13/02/13 06:45, Barry Warsaw wrote:
[...]
> IMHO, none of these approach the simplicity and explicitness of this API:
>
> class Color(Enum):
>      RED = 1
>      GREEN = 2
>      BLUE = 3
>
> class FieldType(Enum):
>      BINARY = 1
>      AUTOINC = 2
>      NULLABLE = 4
>
> The savings in a few characters, does not (again IMHO) make up for all the
> magic and implicitness you have to guess at with the top versions.
>
> I also don't find much value in the 'unique' style, which seem like they're
> just another way to name string constants.  Here though, you could argue that
> the DRY principle at least makes them interesting, since IIUC, the explicit
> alternative would be
>
> class Geometry:
>      LEFT = 'left'
>      RIGHT = 'right'
>      TOP = 'top'
>      # ... and so on ...
>
> I just wouldn't call these "enums" though. ;)  Again, being a little more
> explicit seems like a win, or at least not so bad.

My perspective from the peanut gallery is, not so. That "little more"
explicitness actually raises the barrier to using enums enough that they
are underused. In my experience, good practice or not, too people avoid
defining enum-like constants:

LEFT = 'left'
RIGHT = 'right'
...

and just embed the string literals in their code instead.

def move(distance, direction):
     if direction == 'left':
         ...


It's hard to avoid the "magic constant" anti-pattern, and too easy to fall
into the bad habit.

Speaking as an ex-Pascal programmer, I really miss the simplicity of creating
enumerated types.

type
   units = (inches, feet, furlongs, miles);
   relationship = (parent, sibling, child);


which would correspond to Tim's suggestion:


class units(Enum):
     INCHES, FEET, FURLONGS, MILES

class relationship(Enum):
     PARENT, SIBLING, CHILD


I would use that, since I don't really care what the values of the enums are.
All I care is:

- they're unique within a type/class;
- they print like their name (e.g. FEET not 1);
- (optional) they can combine as bitmasks.


Not having to set their value explicitly is a *good thing*. If I don't know
the underlying value, I'm not tempted to do this:

some_func(42, unit=1)  # should be unit=FEET


But if I had to use something like this:

class units(Enum):
     INCHES = val()
     FEET = val()
     FURLONGS = val()
     MILES = val()


or this:

class relationship(Enum):
     PARENT, SIBLING, CHILD = range(3)


I'd probably wouldn't bother. I'd stick to "poor man's enum", like this:

PARENT, SIBLING, CHILD = range(3)

or (to my shame, but I have to be realistic) magic constants.



-- 
Steven



More information about the Python-ideas mailing list