当不对基础值进行编码时,使用 Enum 有什么优势?
What advantage does using an Enum bring when it's not encoding underlying values?
我理解在将人类可读字符串转换为基础(例如数字)值时使用 Enum
的意义,在 [=22 中使用 FederalHoliday
class =] 就是一个很好的例子。
但我正在考虑的用例只是将函数参数限制为一组可能的值,这些值当前作为 "magic strings" 传递。所以在这里实现 Enum
并不会真正提高代码的可读性(如果有的话,它会使代码更加混乱)。将一个字符串变成 Enum
,只是为了比较实际上相同的字符串(即 Enum
的名称)感觉有点矫枉过正。
列出了枚举的一般优点,但我不确定其中有多少适用于这种情况。
为了澄清我的意思,这里有一个例子,它有一个函数,它打印一个由 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
有什么优势?有什么方法可以使代码更健壮吗? 添加什么吗?
我读过的其他内容:
一般来说主要是关于 Enum
s,尤其是当字符串表示下面的另一个值时:
- How can I represent an 'Enum' in Python?
- Python enum, when and where to use?
这似乎有一个类似于我的例子(在 Enums are interoperable 下),但我很难理解围绕它的技术讨论,它只显示设置 Enum
,未使用它:
好吧,关于代码的清晰度可能取决于人和风格,但枚举使它更清晰,认为如果您需要更改要用作标志的字符串,则必须在使用和时重构所有代码枚举你只需要在枚举 class 中更改它。
对我来说使用枚举是有意义的:
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
你是对的,枚举不是一种静态类型的语言,枚举的好处在 Python 中并不那么强大。许多 API 仍然使用字符串来处理这些事情,而且很好。但是我认为它仍然有好处,特别是从 IDE 支持(自动完成)和静态分析(代码检查)的角度来看。想象一下,您有一个函数可以让您使用不同的方法计算向量的范数。选项 'Euclidean'
、'Absolute'
和 'Manhattan'
、'EUCLIDEAN'
、'ABSOLUTE_VALUE'
和 'TAXICAB'
还是只是“e
”、“a
',和 'm'
?如果你有一个枚举和一个足够好的 IDE,你可以写 NormType.
然后按 Ctrl+Space 来查看选项,而不必再次查看文档。如果你写错了,代码 linter 可能会让你知道。此外,如果您碰巧重命名其中一个选项,应该更容易找到所有需要更改的地方。
也就是说,我同意在某些情况下它可能只会使代码更加混乱。在您的示例中,这些选项可能足够简单,可以毫无问题地使用字符串。无论如何,当在多个地方使用枚举时,枚举的好处变得更加相关,例如具有相似参数的多个函数,您希望在这些地方强制统一并避免代码中愚蠢的字符串拼写错误。很难证明对单个函数的单个参数需要枚举。
我理解在将人类可读字符串转换为基础(例如数字)值时使用 Enum
的意义,在 [=22 中使用 FederalHoliday
class =] 就是一个很好的例子。
但我正在考虑的用例只是将函数参数限制为一组可能的值,这些值当前作为 "magic strings" 传递。所以在这里实现 Enum
并不会真正提高代码的可读性(如果有的话,它会使代码更加混乱)。将一个字符串变成 Enum
,只是为了比较实际上相同的字符串(即 Enum
的名称)感觉有点矫枉过正。
为了澄清我的意思,这里有一个例子,它有一个函数,它打印一个由 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
有什么优势?有什么方法可以使代码更健壮吗? 添加什么吗?
我读过的其他内容:
一般来说主要是关于 Enum
s,尤其是当字符串表示下面的另一个值时:
- How can I represent an 'Enum' in Python?
- Python enum, when and where to use?
这似乎有一个类似于我的例子(在 Enums are interoperable 下),但我很难理解围绕它的技术讨论,它只显示设置 Enum
,未使用它:
好吧,关于代码的清晰度可能取决于人和风格,但枚举使它更清晰,认为如果您需要更改要用作标志的字符串,则必须在使用和时重构所有代码枚举你只需要在枚举 class 中更改它。 对我来说使用枚举是有意义的:
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
你是对的,枚举不是一种静态类型的语言,枚举的好处在 Python 中并不那么强大。许多 API 仍然使用字符串来处理这些事情,而且很好。但是我认为它仍然有好处,特别是从 IDE 支持(自动完成)和静态分析(代码检查)的角度来看。想象一下,您有一个函数可以让您使用不同的方法计算向量的范数。选项 'Euclidean'
、'Absolute'
和 'Manhattan'
、'EUCLIDEAN'
、'ABSOLUTE_VALUE'
和 'TAXICAB'
还是只是“e
”、“a
',和 'm'
?如果你有一个枚举和一个足够好的 IDE,你可以写 NormType.
然后按 Ctrl+Space 来查看选项,而不必再次查看文档。如果你写错了,代码 linter 可能会让你知道。此外,如果您碰巧重命名其中一个选项,应该更容易找到所有需要更改的地方。
也就是说,我同意在某些情况下它可能只会使代码更加混乱。在您的示例中,这些选项可能足够简单,可以毫无问题地使用字符串。无论如何,当在多个地方使用枚举时,枚举的好处变得更加相关,例如具有相似参数的多个函数,您希望在这些地方强制统一并避免代码中愚蠢的字符串拼写错误。很难证明对单个函数的单个参数需要枚举。