【问题标题】:What advantage does using an Enum bring when it's not encoding underlying values?当 Enum 不对底层值进行编码时,使用 Enum 有什么好处?
【发布时间】:2018-10-20 13:20:58
【问题描述】:

我理解在将人类可读的字符串转换为基础(例如数字)值时使用 Enum 的意义,this answer 中的 FederalHoliday 类就是一个很好的例子。

但我正在考虑的用例只是将函数参数限制为一组可能的值,这些值当前作为“魔术字符串”传递。所以在这里实现Enum 并不会真正提高代码的可读性(如果有的话,它会使代码更加混乱)。将字符串转换为Enum,只是为了比较实际上是相同的字符串(即Enum 的名称)感觉有点矫枉过正。

This answer 列出了枚举的一般优势,但我不确定其中有多少适用于这种情况。

为了澄清我的意思,这里有一个例子,它有一个函数可以打印一个由mode指定的特定大小写的字符串:

def print_my_string(my_string, mode):
    if mode == 'l':
        print(my_string.lower())
    elif mode == 'u':
        print(my_string.upper())
    elif mode == 'c':
        print(my_string.capitalize())
    else:
        raise ValueError("Unrecognised mode")

要查看它的实际效果,请运行以下代码:

for mode in ['l', 'u', 'c']:
    print_my_string("RaNdoM CAse StRING", mode)

给予:

random case string
RANDOM CASE STRING
Random case string

所以我的问题是:

当字符串不代表下面的另一个值时,Enum 带来什么优势?有什么方法可以使代码更健壮吗?它添加什么吗?


我读过的其他东西:

主要是关于Enums,特别是当字符串代表下面的另一个值时:

这似乎有一个类似于我的示例(在 Enums are interoperable 下),但我很难理解围绕它的技术讨论,它只显示设置Enum,而不是使用它:

【问题讨论】:

    标签: python python-3.x enums magic-string


    【解决方案1】:

    您是对的,不是静态类型语言,枚举的好处在 Python 中没有那么强大。许多 API 仍然使用字符串来处理这类事情,而且很好。但是我认为它仍然有好处,特别是从 IDE 支持(自动完成)和静态分析(代码 linting)的角度来看。想象一下,您有一个函数可以让您使用不同的方法计算向量的范数。选项是'Euclidean''Absolute''Manhattan''EUCLIDEAN''ABSOLUTE_VALUE''TAXICAB' 还是只是'e'、'a'和'm'?如果你有一个枚举和一个足够好的 IDE,你可以写 NormType. 并按 Ctrl+Space 来查看选项,而不必查看文档再来一次。如果你写错了,代码 linter 可能会让你知道。此外,如果您碰巧重命名了其中一个选项,应该更容易找到所有需要更改的地方。

    也就是说,我同意在某些情况下它可能会使代码更加混乱。在您的示例中,选项可能很简单,可以毫无问题地使用字符串。无论如何,当在多个地方使用枚举时,枚举的好处变得更加相关,例如具有相似参数的几个函数,您希望在这些函数中强制统一并希望避免代码中出现愚蠢的字符串拼写错误。很难证明单个函数的单个参数需要枚举。

    【讨论】:

      【解决方案2】:

      好吧,关于代码的清晰度可能取决于个人和样式,但是 enum 使它更清晰,认为如果您需要更改要用作标志的字符串,则必须在使用时重构所有代码并枚举您只需要在枚举类中更改它。 对我来说使用枚举是有意义的:

      from enum import Enum
      
      class PrintFlag(Enum):
        L = "lower"
        U = "upper"
        C = "capitalize"
      
      def print_my_string(my_string, mode):
          action_dict = {
            PrintFlag.L : str.lower,
            PrintFlag.U : str.upper,
            PrintFlag.C : str.capitalize,
          }
          try:
            print(action_dict[mode](my_string))
          except KeyError:
            raise ValueError("Unrecognised mode")
      
      
      for mode in PrintFlag:
          print_my_string("RaNdoM CAse StRING", mode)
      

      你有一个live example

      【讨论】:

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