Enum vs String作为函数中的参数

Mup*_*pet 13 python coding-style numpy

我注意到现在很多库似乎更喜欢使用字符串而不是enum-type变量来获取参数.

人们之前会使用枚举,例如dateutil.rrule.FR为星期五,似乎这已经转向使用字符串(例如'FRI').

numpy(或pandas)也是如此,其中searchsorted例如使用字符串(例如side ='left'side ='right')而不是定义的枚举.为了避免疑问,在python 3.4之前,这可以很容易地实现为枚举:

class SIDE:
    RIGHT = 0
    LEFT = 1
Run Code Online (Sandbox Code Playgroud)

enums-type变量的优点很明显:你不能在不引发错误的情况下拼错它们,它们为IDE提供了适当的支持等.

那么为什么要使用字符串,而不是坚持使用枚举类型呢?这不会使程序更容易出现用户错误吗?它不像枚举产生开销 - 如果有的话,它们应该稍微更高效.那么这种范式转变的时间和原因何时发生?

ddd*_*bbb 10

我知道这个问题已经得到了解答,但有一件事根本没有得到解决:事实上,当使用 Enum 存储的值时,必须显式调用 Python Enum 对象来获取它们的值。

>>> class Test(Enum):
...     WORD='word'
...     ANOTHER='another'
...
>>> str(Test.WORD.value)
'word'
>>> str(Test.WORD)
'Test.WORD'
Run Code Online (Sandbox Code Playgroud)

解决这个问题的一个简单方法是提供一个实现__str__()

>>> class Test(Enum):
...     WORD='word'
...     ANOTHER='another'
...     def __str__(self):
...             return self.value
... 
>>> Test.WORD
<Test.WORD: 'word'>
>>> str(Test.WORD)
'word'
Run Code Online (Sandbox Code Playgroud)

是的,添加.value并不是什么大不了的事,但仍然带来不便。使用常规字符串不需要额外的工作,不需要额外的类,也不需要重新定义任何默认的类方法。尽管如此,在许多情况下,必须显式转换为字符串值,而简单的转换str不会有问题。


Pau*_*ine 6

[更新]

截至今天(2019 年),Python 引入了数据类——结合可选的类型注释和静态类型分析器(如 mypy),我认为这是一个已解决的问题。

至于效率,与大多数计算机语言相比,Python 中的属性查找有些昂贵,因此我猜出于性能原因,某些库可能仍会选择避免使用它。

【原答案】

恕我直言,这是一个品味问题。有些人喜欢这种风格:

def searchsorted(a, v, side='left', sorter=None):
    ...
    assert side in ('left', 'right'), "Invalid side '{}'".format(side)
    ...

numpy.searchsorted(a, v, side='right')
Run Code Online (Sandbox Code Playgroud)

是的,如果你searchsorted和你一起打电话,side='foo'你可能会AssertionError在运行时得到一个方法 - 但至少这个错误很容易在回溯中被发现。

虽然其他人可能更喜欢(对于您强调的​​优点):

numpy.searchsorted(a, v, side=numpy.CONSTANTS.SIDE.RIGHT)
Run Code Online (Sandbox Code Playgroud)

我赞成第一个,因为我认为很少使用的常量不值得命名空间的浪费。你可能不同意,人们可能会因为其他问题而与任何一方保持一致。

如果您真的在乎,没有什么可以阻止您定义自己的“枚举”:

class SIDE(object):
    RIGHT = 'right'
    LEFT = 'left'

numpy.searchsorted(a, v, side=SIDE.RIGHT)
Run Code Online (Sandbox Code Playgroud)

我认为这不值得,但这又是一个品味问题。

[更新]

斯蒂芬提出了一个公平的观点:

一旦需要更改此类枚举的值,在许多地方查找和替换字符串就不是我的乐趣:-)

我可以看到在没有命名参数的语言中这是多么痛苦 - 使用示例,您必须搜索字符串'right'并获得大量误报。在 Python 中,您可以缩小搜索范围side='right'

当然,如果您正在处理一个已经定义了一组枚举/常量(如外部 C 库)的接口,那么是的,一定要模仿现有的约定。

  • 抱歉,但对我来说,“**Python 引入数据类 - 结合可选类型注释和静态类型分析器(如 mypy**)”以何种方式回答问题或解决问题并不明显。请您给个提示好吗? (12认同)
  • 恕我直言,这不是品味问题。遇到运行时错误是愚蠢的,如果它们以前可以非常简单地避免的话。我真的无法掌握许多/所有著名框架中的用法。 (3认同)

小智 6

我认为枚举更安全,特别是对于有多个开发人员的大型系统.

一旦需要改变这种枚举的价值,在许多地方查找和替换字符串不是我的乐趣:-)

最重要的标准是恕我直言:用于模块甚至包中一个字符串似乎没问题,在公共API中我更喜欢枚举.