volcano volcano - 1 month ago 19
Python Question

Python: enumerated values vs. nameduples

Recently I participated in a discussion about enumeration in Python. Ethan Furman has suggested that there's no need to re-invent the wheel, and when there're standard enum package - no need to play around.

So, after finally switching to 3.5, I tried - and it turns out that string constants defined by enum.Enum do require de-referencing, at least in some APIs.

This is a simplified example of what did not work for me

In [83]: consts = collections.namedtuple('consts', 'PATH')('/usr/bin')

In [84]: consts.PATH
Out[84]: '/usr/bin'

In [85]: os.path.exists(consts.PATH)
Out[85]: True

In [86]: consts = enum.Enum('consts', [['PATH','/usr/bin']])

In [87]: os.path.exists(consts.PATH)
---------------------------------------------------------------------------
TypeError Traceback (most recent call last)
<ipython-input-87-c4641f1a4c50> in <module>()
----> 1 os.path.exists(consts.PATH)

/usr/local/Cellar/python3/3.5.2_1/Frameworks/Python.framework/Versions/3.5/lib/python3.5/genericpath.py in exists(path)
17 """Test whether a path exists. Returns False for broken symbolic links"""
18 try:
---> 19 os.stat(path)
20 except OSError:
21 return False

TypeError: argument should be string, bytes or integer, not consts


That, of course, worked

In [90]: os.path.exists(consts.PATH.value)
Out[90]: True


In my book, any approach that requires adding code all over the project is guilty of being inefficient, so - while thankful for the suggestion! - I am going back to good ol' namedtuple approach.

The question is - why doesn't enum attribute supports implicit dereferencing of attributes? Is it implementation bug in 3.5.2?

Thanks,
Mark

Answer

enum.Enum is meant to be a base class. If you also inherit from str as you're setting up the class, it should work as expected:

In [34]: class consts(str, enum.Enum):
   ....:     PATH = r"C:\Windows"
   ....:

In [35]: consts.PATH
Out[35]: <consts.PATH: 'C:\\Windows'>

In [36]: os.path.exists(consts.PATH)
Out[36]: True