在Python中创建类似C的枚举
也许我已经找到了这个问题的答案,因为这是不可能的,但是如果有一个漂亮的把戏。。。我洗耳恭听。我试图在python中重现以下C枚举列表:在Python中创建类似C的枚举,python,c,enums,Python,C,Enums,也许我已经找到了这个问题的答案,因为这是不可能的,但是如果有一个漂亮的把戏。。。我洗耳恭听。我试图在python中重现以下C枚举列表: enum Id { NONE = 0, HEARTBEAT, //0x1 FLUID_TRANSFER_REQUEST, FLUID_TRANSFER_STATUS_MSG, FLUID_TRANSFER_ERROR_MSG, FLUID_TRANSFER_RESUME, EMERGENCY_STOP_MSG, L
enum Id
{
NONE = 0,
HEARTBEAT, //0x1
FLUID_TRANSFER_REQUEST,
FLUID_TRANSFER_STATUS_MSG,
FLUID_TRANSFER_ERROR_MSG,
FLUID_TRANSFER_RESUME,
EMERGENCY_STOP_MSG,
LOG_MSG,
VERSION_REQUEST,
VERSION_RESPONSE,
CHANNEL_INFORMATION_REQUEST,
CHANNEL_INFORMATION_RESPONSE,
TEST_REQUEST,
LED_CONTROL_REQ,
RESET_REQ,
// Camera App Messages
START_SENDING_PICTURES = 0x010000,
STOP_SENDING_PICTURES,
START_RECORDING_VIDEO_REQ,
STOP_RECORDING_VIDEO_REQ,
TAKE_PICTURE_REQ,
SET_VOLUME_LIMIT,
VIDEO_FRAME_MSG,
PICTURE_MSG,
I_FRAME_REQUEST,
CURRENT_VOLUME,
START_ANALYZING_IMAGES_REQ,
STOP_ANALYZING_IMAGES_REQ,
SET_FILE_PATH,
//Sensor Calibration
VOLUME_REQUEST = 0x020000,
START_CAL,
CLI_COMMAND_REQUEST,
CLI_COMMAND_RESPONSE,
// File Mananger
NEW_DELIVERY_REQ = 0x30000,
GET_DELIVERY_FILE_REQ,
GET_FILE_REQ,
ACK_NACK,
RESPONSE,
LAST_ID
};
但是,我不想为列表指定每个值,因为它经常更改。由于我在各个部分中也将其设置为新值,因此无法使用自动编号方法(例如,VOLUME_REQUEST=0x020000)。有人想出了一个在python中复制C风格枚举的巧妙方法,还是我一直在艰难地复制它?也许你可以在python 3中使用一些C风格枚举的变体。对于Python2,我只做了以下操作(在每行末尾加括号以避免出现难看的
\
):
要处理多个范围,只需使用多个单独的range()。缺点是必须显式指定最终值
中似乎也有一些更奇特的方法,但上面的方法应该最接近C风格的enum
,语法开销最小
这不是一个严肃的建议,但如果您喜欢神秘的代码和有问题的做法,那么下面的破解似乎也适用于C风格的枚举
(需要注意的是,枚举数总是在模块范围内创建的)。你可以尽情地唠叨
create_var_range()
逐步遍历其名称的变量参数列表,并为每个变量创建一个变量,从first_val
开始分配递增的整数值。它使用了globals()
函数,该函数返回带有全局符号表的字典。如果适用,请参阅适用于Python 3.4的。我是根据我在这里找到的东西写代码的
这主要是一种黑客行为,因为我确信有一种更有效的方法来解决我所做的事情
from enum import IntEnum
import re
class AutoNumber(IntEnum):
def __new__(cls, *args):
numberList = re.findall(r'\d+', str(cls._member_map_))
if len(cls.__members__) > 0 and not args:
prevMax = max(map(int, numberList))
value = prevMax + 1
print(format(value, '#04x'))
else:
value = args[0]
print(format(value, '#04x'))
integer = int.__new__(cls)
integer._value_ = value
return integer
class EnumClass(AutoNumber):
NONE = 0
HEARTBEAT = () # 0x1
FLUID_TRANSFER_REQUEST = ()
# ...
# Camera App Messages
START_SENDING_PICTURES = 0x010000
STOP_SENDING_PICTURES = ()
START_RECORDING_VIDEO_REQ = ()
# ...
# Sensor Calibration
VOLUME_REQUEST = 0x020000
START_CAL = ()
# ...
# File Mananger
NEW_DELIVERY_REQ = 0x30000
GET_DELIVERY_FILE_REQ = ()
GET_FILE_REQ = ()
# ...
此“枚举”输出有效地包括:
0x00 # NONE
0x01
0x02
...
0x10000 # START_SENDING_PICTURES
0x10001
0x10002
...
0x20000 # VOLUME_REQUEST
0x20001
...
0x30000 # NEW_DELIVERY_REQ
0x30001
0x30002
...
注意,输出是在使用print语句创建项时产生的,它是为了调试目的,但这是我获得数据的最好方法。作者的一个新方法有一些额外的优点(例如基于类的NamedTuple
和常量
类)
如果您使用Python 3,其中一个很酷的功能是内置的自动编号:
from aenum import Enum
class Id(Enum, start=0):
#
_auto_on_ # needed since aenum 3.0
#
NONE # 0x0
HEARTBEAT # 0x1
FLUID_TRANSFER_REQUEST
FLUID_TRANSFER_STATUS_MSG
FLUID_TRANSFER_ERROR_MSG
# ...
# Camera App Messages
START_SENDING_PICTURES = 0x010000
STOP_SENDING_PICTURES
START_RECORDING_VIDEO_REQ
STOP_RECORDING_VIDEO_REQ
# ...
# Sensor Calibration
VOLUME_REQUEST = 0x020000
START_CAL
CLI_COMMAND_REQUEST
CLI_COMMAND_RESPONSE
#
# File Mananger
NEW_DELIVERY_REQ = 0x30000
GET_DELIVERY_FILE_REQ
GET_FILE_REQ
#
ACK_NACK
RESPONSE
#
LAST_ID
在使用中:
print(repr(Id.HEARTBEAT))
# <Id.HEARTBEAT: 1>
print(repr(Id.STOP_SENDING_PICTURES))
# <Id.STOP_SENDING_PICTURES: 65537>
print(repr(Id.VOLUME_REQUEST))
# <Id.VOLUME_REQUEST: 131072>
打印(repr(Id.HEARTBEAT))
#
打印(报告(Id.停止发送图片))
#
打印(报告(Id.VOLUME_请求))
#
I使用工作代码进行了更新。这主要是一个黑客攻击,但实际上是一个自我更新的枚举。我不太喜欢每次枚举后的=()
,但这做了我想要的工作。谢谢谢谢我想这个和@Saturisk答案对我来说是有用的。我只需要选择我想用哪一个:)@David,我在发布之前确实看到了,但我认为它没有很好地满足我的具体要求。我相信下面的答案更适合这个特殊的要求。这里的答案是那里答案的一个子集,是对那里答案的一种苍白模仿。我建议你仔细阅读这些答案。我只是浏览了这些答案,但没有一个能回答OP的问题。如果您对我的证书感兴趣:我是的和的主要作者。这很酷,可能是最干净、最简单的解决方案,但我当时没有这个库。我相信我们只限于外部图书馆。不错的解决方案@Ethan:)@ls6777:谢谢!如果你喜欢,可以投赞成票我确实投了赞成票,但在我获得15个代表点之前,它不会公开显示;)啊,好的。谢谢@罗伯托:请提供更多细节——我刚刚用最新版本的aenum和Python进行了测试,效果很好。
from aenum import Enum
class Id(Enum, start=0):
#
_auto_on_ # needed since aenum 3.0
#
NONE # 0x0
HEARTBEAT # 0x1
FLUID_TRANSFER_REQUEST
FLUID_TRANSFER_STATUS_MSG
FLUID_TRANSFER_ERROR_MSG
# ...
# Camera App Messages
START_SENDING_PICTURES = 0x010000
STOP_SENDING_PICTURES
START_RECORDING_VIDEO_REQ
STOP_RECORDING_VIDEO_REQ
# ...
# Sensor Calibration
VOLUME_REQUEST = 0x020000
START_CAL
CLI_COMMAND_REQUEST
CLI_COMMAND_RESPONSE
#
# File Mananger
NEW_DELIVERY_REQ = 0x30000
GET_DELIVERY_FILE_REQ
GET_FILE_REQ
#
ACK_NACK
RESPONSE
#
LAST_ID
print(repr(Id.HEARTBEAT))
# <Id.HEARTBEAT: 1>
print(repr(Id.STOP_SENDING_PICTURES))
# <Id.STOP_SENDING_PICTURES: 65537>
print(repr(Id.VOLUME_REQUEST))
# <Id.VOLUME_REQUEST: 131072>