字符串枚举

在我的应用程序中,我在 JSON API 中传递错误原因,如下所示:{"ok": false, "reason": "EMAIL_ALREADY_REGISTERED"}。但是,使用像这样的纯字符串很容易出现错误,例如仅键入"EMAIL_REGISTERED"或各种拼写错误。

所以我考虑创建一些实用程序来只允许固定的值集。我的第一个想法是枚举:

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

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

  • 有一些我不需要的不必要的数值

  • 传递此值时序列化它:str创建"ErrorReason.EXCEPTION",但我也可以执行ErrorReason.EXCEPTION.name, or .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)

有关如何动态创建类的信息,请参阅本答案的开头。


沧海一幻觉
浏览 99回答 2
2回答

弑天下

您可以使用自动枚举值auto()并更改和的行为__str__:from enum import Enum, autoclass 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。

浮云间

有一些我不需要的不必要的数值你需要它们。这实际上就是您返回的内容。我知道您只需要 或 之一是什么意思name,value但最好保持它们相同。auto对此有帮助。在传递该值时序列化它:str创建“ErrorReason.EXCEPTION”,但我也可以执行ErrorReason.EXCEPTION.name或.value(获取数值),并且flask.jsonify默认不支持它,所以我需要设置一个 JSON 序列化器子类确实,Enum不可序列化。默认情况下这会失败from enum import Enumimport jsonclass ErrorReason(Enum):    EXCEPTION = "EXCEPTION"    EMAIL_ALREADY_REGISTERED = "EMAIL_ALREADY_REGISTERED"    PASSWORD_TOO_SHORT = "PASSWORD_TOO_SHORT"print(json.dumps({"exc": ErrorReason.EXCEPTION}))和TypeError: Object of type ErrorReason is not JSON serializablestr这就是为什么鼓励与(看看父母)一起使用它的原因。from enum import Enumimport jsonclass ErrorReason(str, Enum):    EXCEPTION = "EXCEPTION"    EMAIL_ALREADY_REGISTERED = "EMAIL_ALREADY_REGISTERED"    PASSWORD_TOO_SHORT = "PASSWORD_TOO_SHORT"print(json.dumps({"exc": ErrorReason.EXCEPTION}))使用 mixin 可以很好地序列化str。
打开App,查看更多内容
随时随地看视频慕课网APP

相关分类

Python