我想定义常量,例如A = 10; B = 20
,具有以下属性:
A.value + B.value == 30
(甚至A + B == 30
)A = 10; B = 10
A.name == "A"
[v.name for v in CONSTANTS]
from config import CONSTANTS
最后,属性#6是问题所在。像
这样的东西A = 10
B = 20
A_NAME = "A"
B_NAME = "B"
CONSTANTS = { A_NAME: A, B_NAME: B }
基本上就是解决方案。但我想避免使用这个冗长的代码(如果可能的话)。
这种尝试非常接近:
import enum
class CONSTANTS(enum.IntEnum):
A = 10
B = 20
assert CONSTANTS.A + CONSTANTS.B == 30
assert CONSTANTS.A.name == "A"
assert CONSTANTS.__members__.keys() == ["A", "B"]
assert CONSTANTS.__members__.values() == [10, 20]
但是当两个常量具有相同的值(属性#2)时失败。还可以使用Enum
构造函数定义value
的子类。但同样,A = 10; B = 10
将映射到同一个实例,即使名称不同。现在,人们还可以添加一个名称(或任何其他未使用的,但与构造函数不同的参数),以使这个问题消失。但我认为这种做法不洁净。例如,A = ("A", 10); B = ("B", 10); def __init__(self, _, value): ...
。
答案 0 :(得分:0)
使用globals()
将dict内容复制到全局变量中,可以使CONSTANTS dict更简洁:
CONSTANTS = {"A": 10, "B": 20}
globals().update(CONSTANTS)
print(B) # prints 20
答案 1 :(得分:0)
您是否考虑过使用namedtuple集合?
from collections import namedtuple
IntConst = namedtuple('IntConst', ['name', 'value'])
A = IntConst('A',10)
B = IntConst('B',20)
他们满足您的正常访问"按字段......
A.value + B.value
当多个IntConst
具有相同的值时,他们不会抱怨...
A = IntConst('A',10)
B = IntConst('B',10)
他们会给出一个相关的字符串......
A.name
他们将允许列出......
CONSTANTS = list()
CONSTANTS.extend([A,B])
[v.name for v in CONSTANTS]
您的IDE可能已经支持namedtuple
。添加更多常量只需要您创建IntConst
namedtuple
的实例。对于导入,您只需在命名空间中创建这些IntConst
值的列表,它们就会成为import
语句的有效目标。
他们唯一没有给出你要求的是能够从中输入整数值的能力。相反,您将获得包含IntConst
个实例的元组。
>>> A+B
('A', 10, 'B', 10)
答案 2 :(得分:0)
免责声明:不鼓励访问隐藏属性,因此不应将其视为“干净”的解决方案!
标准枚举模块可以调整以提供所需的行为。
import enum
class Const1(enum.Enum):
A = 42
B = 42
def __init__(self, size):
self._value_ = (self.name, size)
self.size = size
class Const2(enum.IntEnum):
A = 42
B = 42
def __init__(self, size):
enum.IntEnum.__init__(self)
self._value_ = (self.name, size)
使用成员名称填充_value_
属性,使alias lookup mechanism无法找到具有相同值的其他成员。唯一的缺点是生成成员的value
属性都引用其内部_value_
属性。实际上,value
被定义为DynamicClassAttribute
。因此,如果不进行进一步修改,我们将面临:Const1.A.value == ('A', 42)
。
如果需要,可以使用属性覆盖此行为。
@property
def value(self):
return self._value_[1]