美文网首页
枚举 enum

枚举 enum

作者: butters001 | 来源:发表于2021-02-26 15:34 被阅读0次

    以下内容基本来自python官方文档,有兴趣的同学可以去查看原文档

    枚举表示的是常量,因此,建议枚举成员名称使用大写字母。
    本模块定义了四个枚举类,用来定义名称与值的唯一组合: EnumIntEnumFlagIntFlag。此外,还定义了一个装饰器,unique(), 和一个辅助类,auto

    1. 定义一个基础的枚举类

    枚举是由 class句法创建的,这种方式易读、易写。
    from enum import Enum
    
    class Color(Enum):
        RED = 1
        GREEN = 2
        BLUE = 3
    

    注解:成员值(如上例中的1,2,3)可以是 intstr 等。若无需设定确切值,auto 实例可以自动为成员分配合适的值。将 auto 与其他值混用时必须要慎重。

    注解:虽然 Enum 由 class 语法创建,但 Enum 并不是常规的 Python 类。

    注解:

    • Color.REDColor.GREEN 等属性是 枚举成员 (或 enum 成员),也是常量。
    • 枚举成员具有 名称 和 值 (例如 Color.RED 的名称为 REDColor.BLUE 的值为 3 等等)
    枚举成员的字符串表现形式更容易理解
    In [16]: print(Color.RED)
    Color.RED
    
    同时,它的 repr 包含更多信息:
    In [18]: print(repr(Color.RED))
    <Color.RED: 1>
    
    枚举成员的 类型 就是它所属的枚举:
    In [19]: type(Color.RED)
    Out[19]: <enum 'Color'>
    
    In [20]: isinstance(Color.GREEN, Color)
    Out[20]: True
    
    Enum 成员还包含 name 和 value 属性:
    In [21]: Color.RED.name
    Out[21]: 'RED'
    
    In [22]: Color.RED.value
    Out[22]: 1
    
    枚举按定义的顺序进行迭代:

    这里可以看出,枚举类和普通的python类是不一样的,遍历这点就不同。

    In [23]: for color in Color:
        ...:     print(color)
        ...: 
    Color.RED
    Color.GREEN
    Color.BLUE
    
    枚举成员可哈希,可用于字典和集合:
    In [24]: apples = {}
    
    In [25]: apples[Color.RED] = 'red delicious'
    
    In [26]: apples[Color.GREEN] = 'granny smith'
    
    In [27]: apples == {Color.RED: 'red delicious', Color.GREEN: 'granny smith'}
    Out[27]: True
    

    2. 枚举成员及其属性的访问

    有时,要在程序中访问枚举成员(如,开发时不知道颜色的确切值,Color.RED 不适用的情况)。Enum 支持如下访问方式:
    In [28]: Color(1)
    Out[28]: <Color.RED: 1>
    
    In [29]: Color(3)
    Out[29]: <Color.BLUE: 3>
    
    用 name 访问枚举成员时,可使用项目名称:
    In [30]: Color['RED']
    Out[30]: <Color.RED: 1>
    
    In [31]: Color['GREEN']
    Out[31]: <Color.GREEN: 2>
    
    可访问枚举成员的 name 或 value:
    In [32]: member = Color.RED
    
    In [33]: member.name
    Out[33]: 'RED'
    
    In [34]: member.value
    Out[34]: 1
    

    3. 重复的枚举成员和值

    两个枚举成员的名称不能相同:

    In [35]: class Shape(Enum):
        ...:     SQUARE = 2
        ...:     SQUARE = 3
        ...: 
    ---------------------------------------------------------------------------
    TypeError                                 Traceback (most recent call last)
    ...
    TypeError: Attempted to reuse key: 'SQUARE'
    

    但是,两个枚举成员可以有相同的值。假设,成员 A 和 B 的值相同(先定义的是 A),则 B 是 A 的别名。按值查找 A 和 B 的值返回的是 A。按名称查找 B,返回的也是 A:

    In [36]: class Shape(Enum):
        ...:     SQUARE = 2
        ...:     DIAMOND = 1
        ...:     CIRCLE = 3
        ...:     ALIAS_FOR_SQUARE = 2
        ...: 
    
    In [37]: Shape.SQUARE
    Out[37]: <Shape.SQUARE: 2>
    
    In [38]: Shape.ALIAS_FOR_SQUARE
    Out[38]: <Shape.SQUARE: 2>
    
    In [39]: Shape(2)
    Out[39]: <Shape.SQUARE: 2>
    

    4. 确保唯一枚举值

    默认情况下,枚举允许多个名称作为一个值的别名。如需禁用此行为,下述装饰器可以确保枚举中的值仅能只用一次:
    @enum.unique

    In [40]: from enum import Enum, unique
    In [41]: @unique
        ...: class Mistake(Enum):
        ...:     ONE = 1
        ...:     TWO = 1
        ...: 
    ---------------------------------------------------------------------------
    ValueError                                Traceback (most recent call last)
    ...
    ValueError: duplicate values found in <enum 'Mistake'>: TWO -> ONE
    

    5. 使用自动设定的值

    如果确切的值不重要,你可以使用 auto:

    In [42]: from enum import Enum, auto
    
    In [43]: class Color(Enum):
        ...:     RED = auto()
        ...:     BLUE = auto()
        ...:     GREEN = auto()
        ...: 
    
    In [44]: list(Color)
    Out[44]: [<Color.RED: 1>, <Color.BLUE: 2>, <Color.GREEN: 3>]
    

    值将由 generate_next_value() 来选择,该函数可以被重载:

    In [45]: class AutoName(Enum):
        ...:     def _generate_next_value_(name, start, count, last_values):
        ...:         return name
        ...: 
        ...: class Ordinal(AutoName):
        ...:     NORTH = auto()
        ...:     SOUTH = auto()
        ...:     EAST = auto()
        ...:     WEST = auto()
        ...: 
    
    In [46]: list(Ordinal)
    Out[46]: 
    [<Ordinal.NORTH: 'NORTH'>,
     <Ordinal.SOUTH: 'SOUTH'>,
     <Ordinal.EAST: 'EAST'>,
     <Ordinal.WEST: 'WEST'>]
    

    Enum中有 _generate_next_value_ 方法,这里被覆盖。

    6. 迭代

    对枚举成员的迭代不会迭代出别名部分:

    In [47]: list(Shape)
    Out[47]: [<Shape.SQUARE: 2>, <Shape.DIAMOND: 1>, <Shape.CIRCLE: 3>]
    

    特殊属性 __members__是一个从名称到成员的只读有序映射。 它包含枚举中定义的所有名称,包括别名:

    In [49]: for name, member in Shape.__members__.items():
        ...:     print(name, member)
        ...: 
        ...: 
    SQUARE Shape.SQUARE
    DIAMOND Shape.DIAMOND
    CIRCLE Shape.CIRCLE
    ALIAS_FOR_SQUARE Shape.SQUARE
    

    __members__ 属性可被用于对枚举成员进行详细的程序化访问。 例如,找出所有别名:

    In [50]: [name for name, member in Shape.__members__.items() if member.name != name]
    Out[50]: ['ALIAS_FOR_SQUARE']
    

    7. 比较

    枚举成员是按标识号进行比较的:

    In [51]: Shape.SQUARE is Shape.SQUARE
    Out[51]: True
    
    In [52]: Shape.SQUARE is Shape.CIRCLE
    Out[52]: False
    
    # 和别名相等
    In [53]: Shape.SQUARE is Shape.ALIAS_FOR_SQUARE
    Out[53]: True
    

    枚举值之间的排序比较 不被 支持。 Enum 成员不属于整数。即不能进行 ><比较。

    In [55]: Shape.SQUARE > Shape.CIRCLE
    ---------------------------------------------------------------------------
    TypeError                                 Traceback (most recent call last)
    <ipython-input-55-811bd6fff84e> in <module>
    ----> 1 Shape.SQUARE > Shape.CIRCLE
    
    TypeError: '>' not supported between instances of 'Shape' and 'Shape'
    

    相等比较的定义如下:

    In [56]: Shape.SQUARE == Shape.CIRCLE
    Out[56]: False
    
    In [57]: Shape.SQUARE != Shape.CIRCLE
    Out[57]: True
    
    In [58]: Shape.SQUARE == Shape.ALIAS_FOR_SQUARE
    Out[58]: True
    

    与非枚举值的比较将总是不相等

    In [59]: Shape.SQUARE == 2
    Out[59]: False
    

    8. 允许的枚举成员和属性

    以上示例使用整数作为枚举值。 如果值 确实 重要,则枚举可以使用任意的值。
    枚举属于 Python 的类,并可具有普通方法和特殊方法。 如果我们有这样一个枚举:

    class Mood(Enum):
        FUNKY = 1
        HAPPY = 3
    
        def describe(self):
            # self is the member here
            # 在这里self 表示枚举的成员
            return self.name, self.value
    
        def __str__(self):
            return 'my custom str! {0}'.format(self.value)
    
        @classmethod
        def favorite_mood(cls):
            # cls here is the enumeration
            # 在这里cls表示枚举对象
            return cls.HAPPY
    

    那么:

    In [61]: Mood.favorite_mood()
    Out[61]: <Mood.HAPPY: 3>
    
    In [62]: Mood.HAPPY.describe()
    Out[62]: ('HAPPY', 3)
    
    In [63]: str(Mood.FUNKY)
    Out[63]: 'my custom str! 1'
    

    9. 封存

    枚举可以被封存与解封:

    In [65]: from pickle import dumps, loads
    
    In [66]: Color is loads(dumps(Color))
    Out[66]: True
    

    10. 功能性 API

    Enum 类属于可调用对象,它提供了以下功能性 API:

    In [67]: Animal = Enum('Animal', 'ANT BEE CAT DOG')
    
    In [68]: Animal
    Out[68]: <enum 'Animal'>
    
    In [69]: Animal.ANT
    Out[69]: <Animal.ANT: 1>
    
    In [70]: Animal.ANT.value
    Out[70]: 1
    
    In [71]: list(Animal)
    Out[71]: [<Animal.ANT: 1>, <Animal.BEE: 2>, <Animal.CAT: 3>, <Animal.DOG: 4>]
    

    第一个参数是枚举的名称。
    第二个参数是枚举成员名称的 来源。 它可以是一个用空格分隔的名称字符串、名称序列、键/值对 2 元组的序列,或者名称到值的映射(例如字典)。 最后两种选项使得可以为枚举任意赋值;其他选项会自动以从 1 开始递增的整数赋值(使用 start 形参可指定不同的起始值)。

    11. 派生的枚举

    IntEnum

    所提供的第一个变种 Enum 同时也是 int 的一个子类。 IntEnum 的成员可与整数进行比较;通过扩展,不同类型的整数枚举也可以相互进行比较:

    In [72]: from enum import IntEnum
        ...: class Shape(IntEnum):
        ...:     CIRCLE = 1
        ...:     SQUARE = 2
        ...: 
        ...: class Request(IntEnum):
        ...:     POST = 1
        ...:     GET = 2
        ...: 
    
    In [73]: Shape == 1
    Out[73]: False
    
    In [74]: Shape.CIRCLE == 1
    Out[74]: True
    
    In [75]: Shape.CIRCLE == Request.POST
    Out[75]: True
    

    不过,它们仍然不可与标准 Enum 枚举进行比较:

    In [76]: class Shape(IntEnum):
        ...:     CIRCLE = 1
        ...:     SQUARE = 2
        ...: 
        ...: class Color(Enum):
        ...:     RED = 1
        ...:     GREEN = 2
        ...: 
    
    In [77]: Shape.CIRCLE == Color.RED
    Out[77]: False
    

    IntEnum 值在其他方面的行为都如你预期的一样类似于整数:

    In [78]: int(Shape.CIRCLE)
    Out[78]: 1
    
    In [79]: ['a', 'b', 'c'][Shape.CIRCLE]
    Out[79]: 'b'
    
    In [80]: [i for i in range(Shape.SQUARE)]
    Out[80]: [0, 1]
    
    IntFlag

    未完待续。。。

    相关文章

      网友评论

          本文标题:枚举 enum

          本文链接:https://www.haomeiwen.com/subject/hximfltx.html