【问题标题】:Porting C defines the Pythonic way移植 C 定义了 Pythonic 方式
【发布时间】:2015-11-19 13:43:50
【问题描述】:

tl;dr 指定大量已定义位掩码和常量的 Pythonic (Py 3) 方式是什么?使用 Enum(s) 还是仅使用大量 const 作为类变量?以及优缺点?

背景

我正在将 C 代码移植到 Python 3。在 C 代码中有大量用作位掩码的定义:

#define ERR_1 = 0x8
#define ERR_2 = 0x2
#define ERR_4 = 0x100
...

我认为在 Python 中使用 Enum 的 Pythonic 方式是使用 IntEnum,这意味着我不必像普通的 Enum 那样在任何地方都使用 .value

from enum import IntEnum

class Errors(IntEnum):
    BROKEN = 0x8
    FUBARED = 0x4
    GIVEUP = 0x7

print(0xFF & Errors.BROKEN)

但它仍然比只拥有print(0xFF & ERR_1) 更冗长,如果我将它们都作为常量,我可以得到它。

【问题讨论】:

  • 如果您希望它们不那么冗长,您可以将它们命名为 e1e2e4(使用 C 代码)并将它们用作 Errors.e2。无论如何,我认为枚举是要走的路,vervose 总是好的(特别是如果你计划发展/维护软件)。

标签: python enums constants


【解决方案1】:

我认为使用 enum 更符合 Python 风格 - 创建该模块付出了很多努力,而且并非没有原因。

“标准”的方式是使用常量(如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】:

    这一切都取决于。

    如果常量在逻辑上是整数(你可以用它们进行算术、按位逻辑等),它们应该是常规的全局变量。标志值在此处,与 os.open() 的各种标志一样,但如果您只是指定一个常量来指示要执行的操作,则枚举更合适(或者更好的是,多个驱动程序函数)。

    当您有一组(相对)较小的值时,通常使用枚举类型,并且这些值大多只是相互比较(例如,if x is MyEnum.FIRST... elif x is MyEnum.SECOND 等)。在这种情况下,您通常不需要IntEnum,因为您一开始不应该经常使用.value。事实上,IntEnum 主要是一种向后兼容的 hack。

    【讨论】:

      【解决方案3】:

      我认为没有任何理由将它们作为课程的一部分。

      errors模块

      # errors.py
      BROKEN = 0x8
      FUBARED = 0x4
      GIVEUP = 0x7
      

      main模块

      import errors
      
      print(0xFF & errors.BROKEN)
      

      【讨论】:

        【解决方案4】:

        使用Enum 绝对是可行的方法,您甚至可以很容易地在模块范围内拥有枚举成员:

        class Errors(IntEnum):
            BROKEN = 0x8
            FUBARED = 0x4
            GIVEUP = 0x7
        globals().update(Errors.__members__)
        

        所以你的比较变成:

        print(0xFF & BROKEN)
        

        关于不使用Enum 的唯一情况是当您有多个名称并不真正重复但映射到相同的值时,因为重复的值都将映射到相同的名称:

        class Bad(Enum):
            BROKEN = 0x01
            MISSING = 0x01
            BLUE = 0x01
        

        但是,如果您对唯一值有不同的名称Enum 是要走的路。

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2019-10-12
          • 1970-01-01
          相关资源
          最近更新 更多