ValueError on Python Enum when comma seperated
Question:
Consider the following code.
How does python interpret class RottenFruit
when it is comma separated? Is this legal? If yes, what is the use case?
from enum import Enum
class Fruit(Enum):
Apple = 4
Orange = 5
Pear = 6
a = Fruit(5)
class RottenFruit(Enum):
Apple = 4,
Orange = 5,
Pear = 6
print(Fruit(5))
print(RottenFruit(5))
output:
Fruit.Orange
Traceback (most recent call last):
File "...testssandbox.py", line 15, in <module>
print(RottenFruit(5))
File "...AppDataLocalProgramsPythonPython36libenum.py", line 291, in __call__
return cls.__new__(cls, value)
File "...AppDataLocalProgramsPythonPython36libenum.py", line 533, in __new__
return cls._missing_(value)
File "...AppDataLocalProgramsPythonPython36libenum.py", line 546, in _missing_
raise ValueError("%r is not a valid %s" % (value, cls.__name__))
ValueError: 5 is not a valid RottenFruit
Answers:
Your second snippet is equivalent to this:
class RottenFruit(Enum):
Apple = (4,)
Orange = (5,)
Pear = 6
In other words, Apple
and Orange
are each tuples of length one.
Let me add a quick explanation. You are running into the combination of two Python features here. One is that you can assign multiple things at once, like this:
x = 7
y = 8
y, x = x, y # Now x = 8 and y = 7
q = [1, 2, 3, 4, 5]
x, m, *r, y = q # Even fancier: now x = 1, m = 2, r = [3, 4] and y = 5
The other is that parsing rules of Python always allow a trailing comma in a list; this is useful for having a list spanning multiple lines look a bit cleaner, and allows a one-element tuple to be defined with e.g. (1,)
. You have found a way to combine these rules in a way that’s not really useful, but isn’t worth preventing.
Consider the following code.
How does python interpret class RottenFruit
when it is comma separated? Is this legal? If yes, what is the use case?
from enum import Enum
class Fruit(Enum):
Apple = 4
Orange = 5
Pear = 6
a = Fruit(5)
class RottenFruit(Enum):
Apple = 4,
Orange = 5,
Pear = 6
print(Fruit(5))
print(RottenFruit(5))
output:
Fruit.Orange
Traceback (most recent call last):
File "...testssandbox.py", line 15, in <module>
print(RottenFruit(5))
File "...AppDataLocalProgramsPythonPython36libenum.py", line 291, in __call__
return cls.__new__(cls, value)
File "...AppDataLocalProgramsPythonPython36libenum.py", line 533, in __new__
return cls._missing_(value)
File "...AppDataLocalProgramsPythonPython36libenum.py", line 546, in _missing_
raise ValueError("%r is not a valid %s" % (value, cls.__name__))
ValueError: 5 is not a valid RottenFruit
Your second snippet is equivalent to this:
class RottenFruit(Enum):
Apple = (4,)
Orange = (5,)
Pear = 6
In other words, Apple
and Orange
are each tuples of length one.
Let me add a quick explanation. You are running into the combination of two Python features here. One is that you can assign multiple things at once, like this:
x = 7
y = 8
y, x = x, y # Now x = 8 and y = 7
q = [1, 2, 3, 4, 5]
x, m, *r, y = q # Even fancier: now x = 1, m = 2, r = [3, 4] and y = 5
The other is that parsing rules of Python always allow a trailing comma in a list; this is useful for having a list spanning multiple lines look a bit cleaner, and allows a one-element tuple to be defined with e.g. (1,)
. You have found a way to combine these rules in a way that’s not really useful, but isn’t worth preventing.