移植C定义了Pythonic方式

时间:2015-08-25 18:03:29

标签: python enums constants

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)更加冗长。

4 个答案:

答案 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)

我觉得它很难看,但是你被两个选项撕裂了,所以我想告诉你如何制作它们。

还值得一读:

答案 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)