# Reimplementing Python's enum.auto() for compatibility

In Python >= 3.6 there is an enum.auto() function.

The auto() function can be used like this:

import enum
from enum import auto

class Fruits(enum.Enum):
APPLE = auto()
ORANGE = auto()
BANANA = auto()


I want to use it, but i cannot be sure if i am on Python >= 3.6 so I implemented it like this:

import enum

try:
from enum import auto
except ImportError:
__my_enum_auto_id = 0
def auto() -> int:
global __my_enum_auto_id
i = __my_enum_auto_id
__my_enum_auto_id += 1
return i

class Fruits(enum.Enum):
APPLE = auto()
ORANGE = auto()
BANANA = auto()


It works afaik, but it seems ugly to me. Any suggestions on how to improove it/make it better? or is it ok?

Is there some side effect I may have overlooked?

• What purpose does i serve? – chepner Oct 7 '17 at 1:28

The easiest solution would be to use the aenum1 library, which is drop-in compatible with the stdlib and also has some advanced features not found in the stdlib. It also works in Python versions 2.7 and 3.3+.

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

• thank you very much! i didnt knew about aenum. and thank you for your effort in general on the stdlib and so on; you do a great work! – linluk Oct 7 '17 at 10:25

Honestly, you won't be able to get anything as good as the built-in code for auto. This is as they've added a clause to _EnumDict.__setitem__ to handle the class.

Since we can't make it so that the values from auto don't start at one for each enum. Such as the following being equivalent:

class A(Enum):
A = auto()
B = auto()

class B(Enum):
A = auto()

class A(Enum):
A = 1
B = 2

class B(Enum):
A = 1


And so the simplest would be to stick with your code, and have the following be equal. (As you done)

class A(Enum):
A = auto()
B = auto()

class B(Enum):
A = auto()

class A(Enum):
A = 1
B = 2

class B(Enum):
A = 3


And so IMO your code is good. The only thing I'd change is make your code not pollute the global namespace with __my_enum_auto_id. And indent with four spaces. This is as easy as using a closure.

def auto_builder():
number = 0
def auto():
nonlocal number
number += 1
return number
return auto

try:
from enum import auto
except ImportError:
auto = auto_builder()
del auto_builder

• thank you for your answer! very informative with perfect detail. i upvoted, but i accepted Ethan Furmans answer. – linluk Oct 7 '17 at 10:27