Python 处理具有多个语义的大量常量的最佳方法
我打算实现一个包含大量常量的库。现在关于stackoverflow上的常量已经有很多问题了。但我正在考虑一个使事情复杂化的特殊情况,我不确定该怎么办。可能有人已经解决了类似的问题,可以帮助我避免明显的失败:) 更准确地说,我将实现SMPP(短消息p2p)相关的东西。SMPP由许多字段组成,这些字段具有不同的可能值,这些值有时由不同的部分组成。例如,esm_类字段为8位整数,位1-0、5-2和7-6为“子字段”。因此,值esm_类由三个“串联”在一起的常量组成 但故事还在继续。esm_类子字段具有不同的含义,具体取决于它们所使用的消息类型 现在出现了几个问题:Python 处理具有多个语义的大量常量的最佳方法,python,Python,我打算实现一个包含大量常量的库。现在关于stackoverflow上的常量已经有很多问题了。但我正在考虑一个使事情复杂化的特殊情况,我不确定该怎么办。可能有人已经解决了类似的问题,可以帮助我避免明显的失败:) 更准确地说,我将实现SMPP(短消息p2p)相关的东西。SMPP由许多字段组成,这些字段具有不同的可能值,这些值有时由不同的部分组成。例如,esm_类字段为8位整数,位1-0、5-2和7-6为“子字段”。因此,值esm_类由三个“串联”在一起的常量组成 但故事还在继续。esm_类子字段具有
- constants.esm_类,其中包含所有esm_类值
- constants.data\包含所有可能编码的编码
- etc(对于每个字段,以常量表示的模块)
- 消息类型子字段的constants.esm_class.types
- 消息模式的constants.esm_class.modes
- 特性字段的constants.esm_class.features
SMPP中的esm_类是一种派生值,由类型、模式和特征组成。例如,如果esm_类的值为00111100,实际上意味着特征等于00,模式等于1111,类型等于00。这就是我所说的“子类型”。常量将与按位运算结合在一起。我将尝试给出一个答案(希望我正确理解了您的意思)。在详细阐述我的上述评论后,我会说:
class esm_class:
BITMASK_FEATURE = 0b11000000
BITMASK_MODE = 0b00111100
BITMASK_TYPE = 0b00000011
class Features:
FEATURE_1 = 0b00
FEATURE_2 = 0b01
FEATURE_3 = 0b10
FEATURE_4 = 0b11
class Modes:
MODE_1 = 0b0000
# …
class Types:
TYPE_1 = 0b00
TYPE_2 = 0b01
# …
def __init__(self, type_, mode, feature):
self.type = type_
self.mode = mode
self.feature = feature
def __bytes__(self):
'''
Use this to write an instance of esm_class to a file-like
object or stream, e.g..:
mysocket.send(bytes(my_esm_class_obj))
'''
return ((self.feature << 6) | (self.mode << 2) |
self.type).to_bytes(1, byteorder='big')
@classmethod
def parse(cls, filelike):
'''
Use this to parse incoming data from a file-like object
and create an instance of esm_class accordingly, e.g:
my_esm_class_obj = esm_class.parse(stream)
'''
instance = cls()
data = filelike.read(1)
instance.feature = int.from_bytes((data & cls.BITMASK_FEATURE) >> 6)
instance.mode = int.from_bytes((data & cls.BITMASK_MODE) >> 2)
instance.mode = int.from_bytes((data & cls.BITMASK_TYPE) >> 2)
等级esm\u等级:
位掩码功能=0b11000000
位掩码_模式=0b00111100
位掩码类型=0b00000011
课程特色:
特征_1=0b00
特征_2=0b01
特征_3=0b10
特征_4=0b11
课程模式:
模式_1=0b0000
# …
类别:
类型_1=0b00
类型_2=0b01
# …
定义初始化(自身、类型、模式、功能):
self.type=type_
self.mode=mode
self.feature=特征
定义字节(自):
'''
使用此选项将esm_类的实例写入如下文件
对象或流,例如…:
发送(字节(我的esm类obj))
'''
返回((self.feature 6)
instance.mode=int.from_字节((数据和cls.BITMASK_模式)>>2)
instance.mode=int.from_字节((数据和cls.BITMASK_类型)>>2)
现在,代码当然可以优化,但关键是:我试图尽快抽象出二进制表示,以获得表示协议中出现的结构的类层次结构。因此,我没有简单地将常量/值放在不同的模块中,而是以这样的方式组织它们,即它们与它们所属的结构一起出现——这也是您将在其余代码中使用的结构
需要注意的其他事项:
- 如果您愿意,您当然可以省略类
、功能
和模式
,并将所有值放在类型
的范围内。但是,只有当符号的名称esm_类
、功能_1
等明确表示它们对应于位字符串的哪一部分时,我才会这样做(即特征部件或模式部件或…)模式_2
- 我通常会避免使用Python 3.4的枚举,因为在我看来,当您需要访问符号的值(即它的
属性)时,它们的处理非常繁琐,但这也是因为我不需要符号本身的名称。您可能会有所不同值
- 最后,在上面的评论中,chepner就是否存储描述i提出了一个非常好的观点