将IntEnum映射到第二组整数

时间:2018-04-19 13:04:21

标签: python python-3.x enums

我已经生成了一个具有不同数据类型的IntEnum

class DataTypes(IntEnum):
    Bytei = 0  # RAM buffer variable            8    bit    (on-off input)
    Byteo = 1  # RAM buffer variable            8    bit    (on-off output)
    Bytem = 2  # RAM buffer variable            8    bit    (flag)
    Wordi = 3  # RAM system variable           16    bit    (signed int)
    Wordo = 4  # RAM system variable           16    bit    (signed int)
    Wordm = 5  # RAM buffer variable           16    bit    (signed int)
    Wordp = 6  # E2PROM variable (parameter)   16    bit    (signed int)
    Dworm = 7  # RAM buffer variable           32    bit    (signed long int)
    Dworp = 8  # E2PROM variable (parameter)   32    bit    (signed long int)

枚举的整数被指定用于通信,所以我想保持这个枚举,因为它或者至少类似的具有相同关联的东西。

在注释中可见数据类型具有不同的大小我想在某种程度上获得数据类型的大小。我可以编写一个函数来映射参数

def map_types(DataType):
    if not 0 <= DataType <=8 :
        size = 0
    elif DataType <3:
        size = 1
    elif DataType <7:
        size = 2
    else:
        size = 4

    return size

但是有一种漂亮,更清洁和/或更多的pythonic方式吗?

2 个答案:

答案 0 :(得分:2)

您希望在size枚举上有一个额外的DataType属性(也可能是__doc__)。您可以自己滚动(如果使用stdlib或enum34 backport,或者利用aenum的高级功能 1

使用enum34(py2 / 3)或stdlib enum(3.4 +)滚动自己:

from enum import IntEnum

class DataTypes(IntEnum):

    def __new__(cls, value, size, doc):
        obj = int.__new__(cls)
        obj._value_ = value
        return obj

    def __init__(self, value, size, doc):
        # value already handled, ignore it
        self.size = size
        self.__doc__ = doc

    Bytei = 0, 8,  'RAM buffer variable         (on-off input)'
    Byteo = 1, 8,  'RAM buffer variable         (on-off output)'
    Bytem = 2, 8,  'RAM buffer variable         (flag)'
    Wordi = 3, 16, 'RAM system variable         (signed int)'
    Wordo = 4, 16, 'RAM system variable         (signed int)'
    Wordm = 5, 16, 'RAM buffer variable         (signed int)'
    Wordp = 6, 16, 'E2PROM variable (parameter) (signed int)'
    Dworm = 7, 32, 'RAM buffer variable         (signed long int)'
    Dworp = 8, 32, 'E2PROM variable (parameter) (signed long int)'

利用aenum的功能(py2 / 3):

from aenum import IntEnum

class DataTypes(IntEnum):

    _init_ = 'value size __doc__'

    Bytei = 0, 8,  'RAM buffer variable         (on-off input)'
    Byteo = 1, 8,  'RAM buffer variable         (on-off output)'
    Bytem = 2, 8,  'RAM buffer variable         (flag)'
    Wordi = 3, 16, 'RAM system variable         (signed int)'
    Wordo = 4, 16, 'RAM system variable         (signed int)'
    Wordm = 5, 16, 'RAM buffer variable         (signed int)'
    Wordp = 6, 16, 'E2PROM variable (parameter) (signed int)'
    Dworm = 7, 32, 'RAM buffer variable         (signed long int)'
    Dworp = 8, 32, 'E2PROM variable (parameter) (signed long int)'

并在使用中:

--> print repr(DataTypes.Bytei)
<DataTypes.Bytei: 0>

--> print DataTypes.Bytei
DataTypes.Bytei

--> print DataTypes.Bytei.size
8

--> print DataTypes.Bytei.__doc__
RAM buffer variable         (on-off input)

1 披露:我是Python stdlib Enumenum34 backportAdvanced Enumeration (aenum)图书馆的作者。

答案 1 :(得分:1)

稍微更简洁的方法是将函数移动到类中。

class DataTypes(IntEnum):
    Bytei = 0  # RAM buffer variable            8    bit    (on-off input)
    Byteo = 1  # RAM buffer variable            8    bit    (on-off output)
    Bytem = 2  # RAM buffer variable            8    bit    (flag)
    Wordi = 3  # RAM system variable           16    bit    (signed int)
    Wordo = 4  # RAM system variable           16    bit    (signed int)
    Wordm = 5  # RAM buffer variable           16    bit    (signed int)
    Wordp = 6  # E2PROM variable (parameter)   16    bit    (signed int)
    Dworm = 7  # RAM buffer variable           32    bit    (signed long int)
    Dworp = 8  # E2PROM variable (parameter)   32    bit    (signed long int)

    @property 
    def size(self):  # You could also link it to the name.  If self.name.startswith('Byte') ...
        if self.value < 3:
            return 1
        elif self.value < 7:
            return 2
        else:
            return 4

    def __repr__(self):
        old_repr = super(DataTypes, self).__repr__()
        return old_repr.replace('>', ', size: {}>'.format(self.size))

for thing in DataTypes:
    print(repr(thing), thing.value, thing.size, 2 < thing, thing < 2, sep=' | ')

输出:

<DataTypes.Bytei: 0, size: 1> | 0 | 1 | False | True
<DataTypes.Byteo: 1, size: 1> | 1 | 1 | False | True
<DataTypes.Bytem: 2, size: 1> | 2 | 1 | False | False
<DataTypes.Wordi: 3, size: 2> | 3 | 2 | True | False
<DataTypes.Wordo: 4, size: 2> | 4 | 2 | True | False
<DataTypes.Wordm: 5, size: 2> | 5 | 2 | True | False
<DataTypes.Wordp: 6, size: 2> | 6 | 2 | True | False
<DataTypes.Dworm: 7, size: 4> | 7 | 4 | True | False
<DataTypes.Dworp: 8, size: 4> | 8 | 4 | True | False

回答以下评论中的具体问题

@property装饰器使方法看起来像一个属性。没有装饰器,为了获得你会调用DataTypes.Bytei.size()的大小。装饰器DataTypes.Bytie.size返回同样的东西。所以@property在这里是不必要的,但我认为,因为它的作用就像是对象的属性而不是方法,所以让它像上面一样工作会很好。

super调用父类的方法。因此,super(DataTypes, self).__repr__()表示使用repr获取self并使用父类中的repr函数(这会返回一个字符串)。然后,因为它是str,实际上是str.replace