tl; dr 什么是Pythonic(Py 3)指定大量定义的位掩码和常量的方法?使用枚举或只是将一组consts作为类变量?和优点/缺点?
背景
我正在将C代码移植到Python 3.在C代码中有大量定义用作位掩码:
#define ERR_1 = 0x8
#define ERR_2 = 0x2
#define ERR_4 = 0x100
...
我认为在python中使用Enum
进行Pythonic方式,我遇到了IntEnum
,这意味着我不必像我一样在任何地方使用.value
正常Enum
:
from enum import IntEnum
class Errors(IntEnum):
BROKEN = 0x8
FUBARED = 0x4
GIVEUP = 0x7
print(0xFF & Errors.BROKEN)
但是,如果我把它们全部作为有力的话,它仍然比print(0xFF & ERR_1)
更加冗长。
答案 0 :(得分:2)
一切都取决于。
如果常量逻辑上是整数(你用它们做算术,按位逻辑等),它们应该是常规的全局变量。与Link的各种标志一样,标志值在此处,但如果您只是指定一个常量来指示要执行的操作,则枚举更合适(或者更好的是,多个驱动程序函数)。
当您拥有(相对)较小的值集时,通常会使用枚举类型,并且这些值通常仅相互比较(例如,使用if x is MyEnum.FIRST... elif x is MyEnum.SECOND
等)。在这种情况下,您通常不需要IntEnum
,因为您不应经常使用.value
开头。实际上,IntEnum
主要是向后兼容的黑客。
答案 1 :(得分:1)
我认为使用enum
更加pythonic - 创建该模块需要付出很多努力,而且没有理由。
"标准"事情的方式是使用常量(如ERR_1
),但这是丑陋的,错误的,真的很难保持。这就是开发该模块的原因。
既然我已经说明了答案,我也建议您同时使用两者:
ERR_1 = 0x8
ERR_2 = 0x4
ERR_3 = 0x7
class Errors(IntEnum):
BROKEN = ERR_1
FUBARED = ERR_2
GIVEUP = ERR_3
print(0xFF & Errors.BROKEN)
print(0xFF & ERR_1)
我觉得它很难看,但是你被两个选项撕裂了,所以我想告诉你如何制作它们。
还值得一读:
enum
模块答案 2 :(得分:1)
使用Enum
绝对是可行的方法,您甚至可以轻松地在模块范围内拥有枚举成员:
class Errors(IntEnum):
BROKEN = 0x8
FUBARED = 0x4
GIVEUP = 0x7
globals().update(Errors.__members__)
所以你的比较变成了:
print(0xFF & BROKEN)
关于唯一一次不使用Enum
是有意义的,当你有几个不是真正重复的名称但映射到相同的值时,因为重复的值都将映射到相同的名称:< / p>
class Bad(Enum):
BROKEN = 0x01
MISSING = 0x01
BLUE = 0x01
但是,如果您有唯一值的不同名称Enum
,那就可以了。
答案 3 :(得分:0)
我认为没有任何理由将它们作为课程的一部分。
errors
模块
# errors.py
BROKEN = 0x8
FUBARED = 0x4
GIVEUP = 0x7
main
模块
import errors
print(0xFF & errors.BROKEN)