3

I have en Enum type:

 class SystemCommands(Enum):
    Get_FW_version = (0, 1)
    Get_MAC_address = (1,1)
    Set_MAC_address = (2,7)
    Get_IP_addr = (3,1)
    Set_IP_addr = (4,5)
    Get_server_IP_addr = (5,1)
    Set_server_IP_addr = (6,5)
    Get_subnet_Mask = (7,1)
    Set_subnet_Mask = (8,5)
    Get_Gateway_Address = (9,1)
    Set_Gateway_Address = (10,5)
    Welcome = (16,1)
    Request_Cannot_Served = (17,1)

    def __init__(self, CommandCode, length):
        self.CommandCode = CommandCode
        self.length = length

I would like to create an enum variable based only on an int value:

code =10
...
Request = SystemCommands(code)

Of course i got a nice excpetion:

 raise ValueError("%r is not a valid %s" % (value, cls.__name__))
ValueError: 10 is not a valid SystemCommands

Question: How can I create a complex-typed enum based only one value?

Jongware
  • 22,200
  • 8
  • 54
  • 100

4 Answers4

0

From the docs,

if your enumeration defines __new__() and/or __init__() then whatever value(s) were given to the enum member will be passed into those methods.

So you can't pass an arbitrary value, you'll need to pass a valid enum member value, say (10, 5)

code = 10, 5
Request = SystemCommands(code)
print(Request)
# SystemCommands.Set_Gateway_Address
Moses Koledoye
  • 77,341
  • 8
  • 133
  • 139
0

If you want to pass multiple values to the Enum constructor but only have one of them be the actual value, then you need to write your own __new__ method:

# using enum34 or the stdlib Enum

from enum import Enum

class SystemCommands(Enum):
    Get_FW_version = (0, 1)
    Get_MAC_address = (1,1)
    Set_MAC_address = (2,7)

    def __new__(cls, CommandCode, length):
        member = object.__new__(cls)
        member._value_ = CommandCode
        member.length = length
        return member

and then

code = ...
request = SystemCommands(code)
print(request)
print(request.name)
print(request.value)
print(request.length)

The process is considerable easier if can use the aenum1 library:

from aenum import Enum

class SystemCommands(Enum):
    _init_ = 'value length'
    Get_FW_version = 0, 1
    Get_MAC_address = 1,1
    Set_MAC_address = 2,7

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

Ethan Furman
  • 63,992
  • 20
  • 159
  • 237
-1
from enum import Enum
class SystemCommands(Enum):
  Get_FW_version = (0, 1)
  Get_MAC_address = (1,1)
  Set_MAC_address = (2,7)
  Get_IP_addr = (3,1)
  Set_IP_addr = (4,5)
  Get_server_IP_addr = (5,1)
  Set_server_IP_addr = (6,5)
  Get_subnet_Mask = (7,1)
  Set_subnet_Mask = (8,5)
  Get_Gateway_Address = (9,1)
  Set_Gateway_Address = (10,5)
  Welcome = (16,1)
  Request_Cannot_Served = (17,1)

  def __init__(self, CommandCode, length):
      self.CommandCode = CommandCode
      self.length = length

# Moses is right but you can also do something like that (workaround)
# use @unique to protect duplicates
code = 10
for val in SystemCommands:
  if val.value[0] == code:
    print (val)

# SystemCommands.Set_Gateway_Address
Ari Gold
  • 1,528
  • 11
  • 18
-1

Thank you Ari, I modified your answer, to be a little more Object Oriented:

class SystemCommands(Enum):
    Get_FW_version = (0, 1)
    Get_MAC_address = (1,1)
    Set_MAC_address = (2,7)
    Get_IP_addr = (3,1)
    Set_IP_addr = (4,5)
    Get_server_IP_addr = (5,1)
    Set_server_IP_addr = (6,5)
    Get_subnet_Mask = (7,1)
    Set_subnet_Mask = (8,5)
    Get_Gateway_Address = (9,1)
    Set_Gateway_Address = (10,5)
    Welcome = (16,1)
    Request_Cannot_Served = (17,1)

    def __init__(self, CommandCode, length):
        self.CommandCode = CommandCode
        self.length = length

    def getCommand(code):
        for val in SystemCommands:
            if code == val.CommandCode:
                return (val)

So now i can use it like this:

Request = SystemCommands.getCommand(code)
print(Request.name)