Python Enum with complex type

本小妞迷上赌 提交于 2021-02-05 06:05:11

问题


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?


回答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



回答2:


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



回答3:


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.




回答4:


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)


来源:https://stackoverflow.com/questions/41483331/python-enum-with-complex-type

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!