如何在实例化类对象时限制可能选择的选项?假设我们有一个如下所示的类,我们希望将 value
值限制为仅在 valueOptions
列表中进行预定义。我的实现尝试如下。是否有更多 Pythonic 方式来实现相同的结果?
class TestClass:
valueOptions = ['A value', 'The value', 'Another value']
def __init__(self, value):
self.value = value
@property
def value(self):
return self._value
@value.setter
def value(self, val):
if val not in self.valueOptions:
raise ValueError('Value not in available options.')
self._value = val
def __str__(self):
return f'Value: {self.value}'
v1 = TestClass('A value') # line 20
v2 = TestClass('Value') # line 21
运行后:
Traceback (most recent call last):
File "<string>", line 21, in <module>
File "<string>", line 5, in __init__
File "<string>", line 14, in value
ValueError: Value not in available options.
最佳答案
如果需要有限的值,请使用 Enum 而不是 str
核心问题是您(隐含地;您的代码未键入)将 value
定义为字符串类型。但是您不需要字符串:您需要一个有限的可能值列表。字符串不是编写该代码的正确变量类型。
enum模块允许您定义具有有限数量的选项/值的枚举类型(类)。
这实际上也解决了另一个问题:您的示例中的值是硬编码的,在您的代码中创建“魔数(Magic Number)”(或在本例中为:“魔数(Magic Number)”)。您的代码最终会在许多不同的地方导致“一个值”、“该值”和“另一个值”的分散实例。如果您(在将来某个时候)决定将“The value”替换为“The best value”,您就会遇到代码维护问题...
这是一个使用枚举(和类型提示)的代码示例:
from enum import Enum
class ValueOptions(Enum):
A_VALUE = 'A value',
THE_VALUE = 'The value',
ANOTHER_VALUE = 'Another value'
class TestClass:
def __init__(self, value: ValueOptions) -> None:
self.value = value
def __str__(self) -> str:
return f'Value: {self.value.name}'
v1 = TestClass(ValueOptions.A_VALUE)
print(v1)
v2 = TestClass(ValueOptions.ILLEGAL_VALUE)
print(v2)
这导致 v1 的代码有效,而 v2 的代码错误:
Traceback (most recent call last):
File ".code.tio", line 19, in <module>
v2 = TestClass(ValueOptions.ILLEGAL_VALUE)
File "/usr/lib64/python3.7/enum.py", line 349, in __getattr__
raise AttributeError(name) from None
AttributeError: ILLEGAL_VALUE
此错误不仅会在运行时显示,而且(甚至更好!)在编写代码时也会显示。任何 Python 代码检查器(例如 mypy
)都会检测到我使用了非法属性:
❯ mypy ./enum_test.py
enum_test.py:21: error: "Type[ValueOptions]" has no attribute "ILLEGAL_VALUE"
Found 1 error in 1 file (checked 1 source file)
最重要的是:此代码比您的版本短一点! ;-)
关于python - 限制类属性值的可能选项,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/74184600/