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?
3 Answers 3
The easiest solution would be to use the aenum
1 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.
-
\$\begingroup\$ 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! \$\endgroup\$linluk– linluk2017年10月07日 10:25:26 +00:00Commented Oct 7, 2017 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
-
\$\begingroup\$ thank you for your answer! very informative with perfect detail. i upvoted, but i accepted Ethan Furmans answer. \$\endgroup\$linluk– linluk2017年10月07日 10:27:20 +00:00Commented Oct 7, 2017 at 10:27
My only suggestion would be to user itertools.count()
instead of implementing your own counter. Something like:
from itertools import count
_global_counter = count()
def auto():
return next(_global_counter)
Explore related questions
See similar questions with these tags.
i
serve? \$\endgroup\$