4

I have defined two enums with attributes. When I want to access an enum element by specifying its attribute it works for enum A (one attribute) but not for enum B (two attributes):

from enum import Enum

class A(Enum):
    ValOne = ('One')
    ValTwo = ('Two')

    def __init__(self, num):
        self.num = num

class B(Enum):
    ValOne = ('Val', 'One')
    ValTwo = ('Val', 'Two')

    def __init__(self, val, num):
        self.val = val
        self.num = num

print(A('One'))
print(B('Val', 'One'))

I get the following output:

A.ValOne
Traceback (most recent call last):
  File "test.py", line 19, in <module>
    print(B('Val', 'One'))
  File "/usr/lib/python3.8/enum.py", line 341, in __call__
    return cls._create_(
  File "/usr/lib/python3.8/enum.py", line 444, in _create_
    _, first_enum = cls._get_mixins_(cls, bases)
  File "/usr/lib/python3.8/enum.py", line 576, in _get_mixins_
    raise TypeError("Cannot extend enumerations")
TypeError: Cannot extend enumerations

What am I missing here?

2 Answers 2

9

UPDATE

In Python 3.12 the effective signature for by-value look-up will be:

B(*values)

So

B('Val', 'One')

will work as expected and return

<B.ValOne: ('Val', 'One')>

while

B(('Val', 'One'))

will continue to work correctly.


The biggest thing you missing is that ('One') is not a tuple -- you need a comma (,), which would look like ('One', ).

So A is made of single, non-tuple, values 'One' and 'Two'.

B, however, is made of tuples, but

 B('Val', 'One')

is not passing a tuple to B, it is passing two arguments: 'Val' and 'One'. As @orlp mentioned, passing a tuple using function syntax looks like:

B(('Val', 'One'))

Finally, in the definitions of A's and B's members, you do not need the parentheses:

class A(Enum):
    ValOne = 'One'
    ValTwo = 'Two'

    def __init__(self, num):
        self.num = num


class B(Enum):
    ValOne = 'Val', 'One'
    ValTwo = 'Val', 'Two'

    def __init__(self, val, num):
        self.val = val
        self.num = num

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

Sign up to request clarification or add additional context in comments.

Comments

4

The correct syntax is B(('Val', 'One')), passing the value of the enum directly (thus in this case a tuple), or simply naming the enum variant by name: B.ValOne.

I must admit this is confusing, with __init__ automagically destructuring the tuple into two arguments. The error isn't helpful either.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.