我想要一个定义一堆常量的文件,这样我以后就不需要对它们进行硬编码。
例如,我会这样做:
@dataclass(frozen=True)
class CONSTANTS:
STATUS_SUCCESS = 200
STATUS_ERROR = 400
SI_UNIT_MASS = "kg"
SI_UNIT_LENGTH = "m"
现在假设我有以下功能:
def func():
something = True
if something:
return CONSTANTS.STATUS_SUCCESS
else:
return CONSTANTS.STATUS_ERROR
我想要
func
的类型提示。
所以我想我可以添加这个:
@dataclass(frozen=True)
class TYPES:
STATUS = Literal[CONSTANTS.STATUS_SUCCESS, CONSTANTS.STATUS_ERROR]
SI_UNIT = Literal[CONSTANTS.SI_UNIT_MASS, CONSTANTS.SI_UNIT_LENGTH]
并更新函数签名:
def func() -> TYPES.STATUS:
但在这里我得到这个错误:
Variable not allowed in type expressionPylancereportInvalidTypeForm
当我写下错误就消失了:
@dataclass(frozen=True)
class TYPES:
STATUS = Literal[200, 400]
SI_UNIT = Literal["kg", "m"]
但这有一个缺点,我可能会忘记向类型添加新的单元或状态代码。我希望这是动态的,这样我就不必重复自己。
有标准方法可以做到这一点吗? 我还想以某种方式重写
CONSTANTS
,这是我想要的
@dataclass(frozen=True)
class CONSTANTS:
STATUS = STATUS
SI_UNIT = SI_UNIT
与
@dataclass(frozen=True)
class STATUS:
SUCCESS = 200
ERROR = 400
...
所以我的想法是,我也许应该让
OPTIONS
和 STATUS
继承自定义类似 TYPE
属性的基类。但我找不到一个感觉自然的例子。
我可以向您展示为什么会出现错误,但这并不能解决您的问题。
首先,错误是什么?它说“类型表达式中不允许变量”。为什么这是有意义的,因为在 python 中没有任何东西是受保护的(或私有的),所有变量都可以改变。例如:
print(func())
# >>> 200
CONSTANTS.STATUS_SUCCESS = "SUCCES"
print(func())
# >>> SUCCES
对于
TYPES.STATUS
变量也会发生同样的情况,当用户将其设置为 TYPES.STATUS = None
时会发生什么?
您可以划分类别并在更有意义的地方使用
ENUM
。或者您可以查看 @overload
装饰器,它可用于定义不同的返回类型,具体取决于输入类型。
这是使用枚举的解决方案:
from enum import IntEnum, StrEnum
class STATUS(IntEnum):
SUCCESS = 200
ERROR = 400
class UNIT(StrEnum):
SI_UNIT_MASS = "kg"
SI_UNIT_LENGTH = "m"
def func() -> STATUS:
something = True
if something:
return STATUS.SUCCESS
else:
return STATUS.ERROR
print(func())
# >>> 200
根据 python 文档: 枚举是一组绑定到唯一值的符号名称。它们与全局变量类似,但它们提供了更有用的 repr()、分组、类型安全和一些其他功能。
用我的话来说,我想说数据类更适合作为存储数据的方法,例如拥有多个用户的 User 类。枚举类包含预定义的数据(在本例中为 SUCCES 和 ERROR)。这就是我建议切换到 ENUM 的原因。
返回值现在是一个 ENUM,但如果您在字符串中使用它,它将打印该值。因此
print(func()) -> 200
但是print(func().__repr__()) -> <STATUS.SUCCESS: 200>
。