字符串枚举

M.沃尔夫:

在我的应用中,我在JSON API中传递了错误原因,如下所示:{"ok": false, "reason": "EMAIL_ALREADY_REGISTERED"}但是,使用这样的纯字符串很容易受到诸如just"EMAIL_REGISTERED"或各种拼写错误之类的错误的影响。

因此,我考虑过创建一些util以仅允许固定的一组值。我的第一个想法是枚举:

from enum import Enum
class ErrorReason(Enum):
    EXCEPTION = 1
    EMAIL_ALREADY_REGISTERED = 2
    PASSWORD_TOO_SHORT = 3

很好,IDE(PyCharm)在键入ErrorReason.E并检查给定值是否有效时会自动向我建议可能的值,但是,它也有缺点:

  • 有一些我不需要的不必要的数值
  • 传递此值时对其进行序列化:strcreated "ErrorReason.EXCEPTION",但我也可以执行ErrorReason.EXCEPTION.name.value(获取数字值),并且flask.jsonify默认情况下不支持此值,因此我需要设置JSON序列化器子类
  • 我也觉得这不是Enum的正确/预期用途

另一种执行此操作的方法可能是:

class ErrorReason:
    EXCEPTION = "EXCEPTION"
    EMAIL_ALREADY_REGISTERED = "EMAIL_ALREADY_REGISTERED"
    PASSWORD_TOO_SHORT = "PASSWORD_TOO_SHORT"

这看起来更干净一些,并且可以ErrorReason.EXCEPTION评估为简单的字符串,但是它也感觉错了–我必须将每个可能的值写两次,并且出于这个唯一目的的对象对我来说太过分了。

实现此目标的最佳方法是什么?或者至少,在保留智能IDE建议的同时,在上一示例中创建两次“哑”简单对象而不键入两次所有内容的最佳方法是什么?


编辑1:我找到了一种生成给定类的方法。但是,即使我生成注释,PyCharm仍然不会执行任何自动完成建议。

_attrs = {"__annotations__": {}}
for reason in ("EXCEPTION", "PASSWORD_TOO_SHORT", "EMAIL_ALREADY_REGISTERED"):
    _attrs[reason] = reason
    _attrs["__annotations__"][reason] = str

ErrorReason = type("ErrorReason", (), _attrs)

有关如何动态创建类的信息,请参见此答案的开头

乌普斯:

你可以使用自动枚举值和改变的行为auto()__str__

from enum import Enum, auto

class ErrorReason(str, Enum):

    def _generate_next_value_(name, start, count, last_values):
        return name

    def __str__(self):
        return self.name

    EXCEPTION = auto()
    EMAIL_ALREADY_REGISTERED = auto()
    PASSWORD_TOO_SHORT = auto()

现在:print(ErrorReason.EMAIL_ALREADY_REGISTERED)将只是EMAIL_ALREADY_REGISTERED

如Tom Wojcik的回答所述,它也继承自str,以使其可序列化json

本文收集自互联网,转载请注明来源。

如有侵权,请联系 [email protected] 删除。

编辑于
0

我来说两句

0 条评论
登录 后参与评论

相关文章