MazeOfEncryption
MazeOfEncryption

Reputation: 405

Is it a bad practice to use enums with non-integer types in python?

Suppose I have a class which extends Enum, named foo; However, instead of using integers for each item, I use strings

from enum import Enum
class foo (Enum):
    foo = "Hello"
    bar = ", "
    foobar = "world"
    barfoo = "!"

When compiling, the system will throw no errors, and happily treat this class as a normal enum. As per why anyone would want to do this, it's very useful if you want to link each name to a data structure, like a dict. Take this as an example:

from enum import Enum
class foo (Enum):
    foo = {"text" : "Hello", "meaning" : "hello"}
    bar = {"text" : ", ", "meaning" : "comma"}
    foobar = {"text" : "world", "meaning" : "world"}
    barfoo = {"text" : "!", "meaning" : "exclamation"}

Well, maze, why not just use a normal class then? Well, its very useful to be able to store this information as an enum, for quick comparison of type. For example, x = {"name" : "foo", "type" : foo.foo} can be easily checked for type with if x[type] is foo.foo.

Is this a "bad practice"? By that, I mean:

  1. Is this an intended use of Enum?
  2. If I took out the (Enum) from class foo (Enum):, would there be any efficiency difference when comparing?
  3. Is there a better way to do what I am wanting to do?

Upvotes: 6

Views: 2842

Answers (1)

Ethan Furman
Ethan Furman

Reputation: 69021

  • Is it a bad practice to use enums with non-integer types in python?

No, it is not bad practice.

  • Is this an intended use of Enum

Yes, Enum was designed to work with non-integer types.

  • If I took out the (Enum) from class foo (Enum):, would there be any efficiency difference when comparing?

The non-Enum version would probably be faster, but that likely doesn't matter. (Test for bottle-necks before guessing what needs to be optimized.)

  • Is there a better way to do what I am wanting to do?

Using mutable types is allowed -- meaning I have taken no steps to prohibit it1 -- but it's generally not a good idea. Enum members should be constant. Your example looks like you want to have two extra attributes on each member: text and meaning -- this is possible on both the stdlib version of Enum, and the Advanced Enumeration version of Enum:

from aenum import AutoNumberEnum

class Foo(AutoNumberEnum):
    _init_ = 'text meaning'
    foo = "Hello", "hello"
    bar = ", ", "comma"
    foobar = "world", "world"
    barfoo = "!", "exclamation"

and in use:

>>> Foo.bar
<Foo.bar: 2>

>>> Foo.bar.text
', '

>>> Foo.bar.meaning
'comma'

See this answer for the stdlib way to accomplish this.


1 Disclosure: I am the author of the Python stdlib Enum, the enum34 backport, and the Advanced Enumeration (aenum) library.

Upvotes: 7

Related Questions