Python 如何方便地定义命名整数常量列表?
我想定义常量,例如Python 如何方便地定义命名整数常量列表?,python,dictionary,global-variables,config,constants,Python,Dictionary,Global Variables,Config,Constants,我想定义常量,例如A=10;B=20,具有以下特性: “正常”访问:例如A.value+B.value==30(甚至A+B==30) 允许重复值:例如A=10;B=10 每个变量的关联字符串:例如A.name==“A” 清单:例如,[v.name代表常数中的v] IDE支持:自动完成名称、重新分解等 添加新常量需要一次更改 可导入:例如,从配置导入常量 归根结底,6号房产才是问题所在。差不多 A = 10 B = 20 A_NAME = "A" B_NAME = "B" CONSTANTS
A=10;B=20,具有以下特性:
“正常”访问:例如A.value+B.value==30
(甚至A+B==30
)
允许重复值:例如A=10;B=10
每个变量的关联字符串:例如A.name==“A”
清单:例如,[v.name代表常数中的v]
IDE支持:自动完成名称、重新分解等
添加新常量需要一次更改
可导入:例如,从配置导入常量
归根结底,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\uuuu init\uuuuu(self,\uuu,value):…
通过使用globals()
将dict内容复制到全局变量中,可以使常量dict内容不那么冗长:
CONSTANTS = {"A": 10, "B": 20}
globals().update(CONSTANTS)
print(B) # prints 20
通过使用globals()
将dict内容复制到全局变量中,您可以减少常量dict内容的冗长程度:
CONSTANTS = {"A": 10, "B": 20}
globals().update(CONSTANTS)
print(B) # prints 20
你有没有考虑过使用这个系列
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)
你有没有考虑过使用这个系列
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)
免责声明:不鼓励访问隐藏属性,因此不应将其视为“干净”解决方案
可以调整标准枚举模块以提供所需的行为
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)
@property
def value(self):
return self._value_[1]
用成员的名称填充\u value\u
属性,会导致无法找到具有相同值的其他成员。唯一的缺点是,生成的成员的值
属性都引用其内部\u值
属性。事实上,值
被定义为。因此,无需进一步修改,我们将面临:Const1.A.value==('A',42)
如果需要,可以使用属性覆盖此行为
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)
@property
def value(self):
return self._value_[1]
免责声明:不鼓励访问隐藏属性,因此不应将其视为“干净”解决方案
可以调整标准枚举模块以提供所需的行为
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)
@property
def value(self):
return self._value_[1]
用成员的名称填充\u value\u
属性,会导致无法找到具有相同值的其他成员。唯一的缺点是,生成的成员的值
属性都引用其内部\u值
属性。事实上,值
被定义为。因此,无需进一步修改,我们将面临:Const1.A.value==('A',42)
如果需要,可以使用属性覆盖此行为
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)
@property
def value(self):
return self._value_[1]
为什么您的提案需要继承自enum
?为什么不能用属性定义类,并根据需要重写\uuuuu add\uuuuu
等?但是我如何访问此类的元素名称呢?对于类C():A=1;B=2
,如何访问C.B.name
或类似的东西?Bleh,疯狂的int子类。它们看起来都很好,也很方便,直到它们传播到一个意想不到的地方,你的程序开始打印疯狂的internaleum。奇怪的名称
而不是3
,或者duck键入检查采用了错误的代码路径,因为它不希望整数具有名称
属性。我完全同意。通过属性访问该值对我来说是完全正确的,当然更安全。@user2357112以消除可能的误解。“疯狂的int子类”是一个很好的东西,但不是必需的。对我来说,“value”属性就足够了。为什么您的提案需要继承自enum
?为什么不能用属性定义类,并根据需要重写\uuuuu add\uuuuu
等?但是我如何访问此类的元素名称呢?对于类C():A=1;B=2
,如何访问C.B.name
或类似的内容