前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >python模块之enum_上

python模块之enum_上

作者头像
枇杷李子橙橘柚
发布2022-06-15 08:05:15
5470
发布2022-06-15 08:05:15
举报
文章被收录于专栏:没有擅长的YcY没有擅长的YcY

enum模块定义了:

  • 4种枚举类:Enum, IntEnum, Flag, IntFlag
  • 装饰器:unique()
  • 助手:auto

Flag, IntFlag, auto在python3.6中加入

创建枚举

代码语言:javascript
复制
from enum import Enum
class Color(Enum):
    RED = 2
    GREEN = 4
    BLUE = 6

注意点: 1. 枚举值可以是任何类型,如果值不重要可以使用auto()自动选择。但在有其他已定义的值的情况下,谨慎与auto混用 2. Color是枚举类,Color.RED等是枚举成员,枚举成员拥有name和value属性 3. 虽然使用class关键字创建,但枚举并不是常规意义上的python类

枚举成员的展现形式:

代码语言:javascript
复制
>>>print(Color.RED)
Color.RED

>>>print(repr(Color.RED))
<Color.RED: 2>

枚举成员的type类型是其所属的枚举类:

代码语言:javascript
复制
>>>type(Color.RED)
<enum 'Color'>
>>>isinstance(Color.RED, Color)
True

枚举支持按照定义时的顺序进行迭代:

代码语言:javascript
复制
>>>for color in Color:
...    print(color)
...
Color.RED
Color.GREEN
Color.BLUE    

枚举成员是可哈希的,因此可以在字典和集合中使用:

代码语言:javascript
复制
>>> apples = {}
>>> apples[Color.RED] = 'red delicious'
>>> apples[Color.GREEN] = 'granny smith'
>>> apples == {Color.RED: 'red delicious', Color.GREEN: 'granny smith'}
True

对枚举成员及其属性的程序化访问

通过值访问枚举成员:

代码语言:javascript
复制
>>>Color(2)
<Color.RED: 2>

通过名称访问枚举成员:

代码语言:javascript
复制
>>>Color["RED"]
<Color.RED: 2>

获取枚举成员的名称和值:

代码语言:javascript
复制
>>>member = Color.RED
>>>member.name
"RED"
>>>member.value
2

枚举成员及其值的重复性问题

拥有两个相同名称的枚举成员是不允许的:

代码语言:javascript
复制
>>> class Shape(Enum):
...     SQUARE = 2
...     SQUARE = 3
...
Traceback (most recent call last):
...
TypeError: Attempted to reuse key: 'SQUARE'

不过不同的枚举成员允许拥有相同的值。后定义的成员是先定义的成员的别名,通过值或名称访问时都将返回先定义的成员:

代码语言:javascript
复制
>>> class Shape(Enum):
...     SQUARE = 2
...     DIAMOND = 1
...     CIRCLE = 3
...     ALIAS_FOR_SQUARE = 2
...
>>> Shape.SQUARE
<Shape.SQUARE: 2>
>>> Shape.ALIAS_FOR_SQUARE
<Shape.SQUARE: 2>
>>> Shape(2)
<Shape.SQUARE: 2>

注意点:任意两个枚举属性(包括成员、方法等)不允许存在相同的名称

枚举值唯一约束

默认情况下,允许多个成员拥有相同的值。使用unique装饰器可以对枚举值进行唯一约束

@enum.unique: 枚举专用的类装饰器。它在枚举的__members__属性中只要查找到成员别名就抛出ValueError异常

代码语言:javascript
复制
>>> from enum import Enum, unique
>>> @unique
... class Mistake(Enum):
...     ONE = 1
...     TWO = 2
...     THREE = 3
...     FOUR = 3
...
Traceback (most recent call last):
...
ValueError: duplicate values found in <enum 'Mistake'>: FOUR -> THREE

自动生成枚举值

对于不重要的枚举值,可以使用auto自动生成:

代码语言:javascript
复制
>>> from enum import Enum, auto
>>> class Color(Enum):
...     RED = auto()
...     BLUE = auto()
...     GREEN = auto()
...
>>> list(Color)
[<Color.RED: 1>, <Color.BLUE: 2>, <Color.GREEN: 3>]

auto生成什么值取决于_generate_next_value_()方法,可重写:

代码语言:javascript
复制
>>> 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()
...
>>> list(Ordinal)
[<Ordinal.NORTH: 'NORTH'>, <Ordinal.SOUTH: 'SOUTH'>, <Ordinal.EAST: 'EAST'>, <Ordinal.WEST: 'WEST'>]

迭代

对枚举成员的迭代,并不会包含成员别名:

代码语言:javascript
复制
>>> list(Shape)
[<Shape.SQUARE: 2>, <Shape.DIAMOND: 1>, <Shape.CIRCLE: 3>]

__members__属性是一个映射了枚举成员及其名称的有序字典,包括成员别名:

代码语言:javascript
复制
>>> for name, member in Shape.__members__.items():
...     name, member
...
('SQUARE', <Shape.SQUARE: 2>)
('DIAMOND', <Shape.DIAMOND: 1>)
('CIRCLE', <Shape.CIRCLE: 3>)
('ALIAS_FOR_SQUARE', <Shape.SQUARE: 2>)

>>> [name for name, member in Shape.__members__.items() if member.name != name]
['ALIAS_FOR_SQUARE']

枚举比较(后两种不适用于IntEnum)

代码语言:javascript
复制
>>> Color.RED is Color.RED
True

>>> Color.RED == Color.BLUE
False

>>> Color.RED < Color.BLUE
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: '<' not supported between instances of 'Color' and 'Color'

>>> Color.BLUE == 6 # 与非枚举的值进行等值比较总是返回False
False

允许的枚举成员与属性

枚举是python类,也可以拥有普通方法和特殊方法:

代码语言:javascript
复制
class Mood(Enum):
    FUNKY = 1
    HAPPY = 3

    def describe(self):
        # self is the member here
        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
        return cls.HAPPY

注意点:如果枚举中定义了__new()__或者__init__()方法,赋值给枚举成员的值将被传递到__new()__或者__init__()

枚举的继承限制

自定义枚举类必须继承自一个枚举基类,至多一个具体的数据类型以及0至多个混合类。继承顺序如下:

代码语言:javascript
复制
class EnumName([mix-in, ...,] [data-type,] base-enum):
    pass

基类枚举如果已经定义了成员,则不能被任何子类继承,如下第一种是不允许的,但第二种可以:

代码语言:javascript
复制
>>> class MoreColor(Color):
...     PINK = 17
...
Traceback (most recent call last):
...
TypeError: Cannot extend enumerations
代码语言:javascript
复制
>>> class Foo(Enum):
...     def some_behavior(self):
...         pass
...
>>> class Bar(Foo):
...     HAPPY = 1
...     SAD = 2
...

不能这么做的原因是可能破坏某些重要的不允许改变的值(原话是would lead to a violation of some important invariants of bytes and instances)。

序列化

代码语言:javascript
复制
>>> from a.b import Color
>>> from pickle import dumps, loads
>>> Color.RED is loads(dumps(Color.RED))
True

一般要求序列化的枚举要定义在模块顶层,因为反序列化要求枚举能够从模块导入。不过在第4版的pickle协议中,已经可以序列化嵌套在类中的枚举

通过在枚举中定义__reduce_ex__()方法,可以修改枚举成员的序列化/反序列化行为

Functional API

枚举类是可调用的:

代码语言:javascript
复制
>>> Animal = Enum("Pet", "Tortoise CAT DOG")

完整的API如下: Enum(value='NewEnumName', names=<...>, *, module='...', qualname='...', type=<mixed-in class>, start=1)

图片描述
图片描述
本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2022-06-15,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 创建枚举
  • 对枚举成员及其属性的程序化访问
  • 枚举成员及其值的重复性问题
  • 枚举值唯一约束
  • 自动生成枚举值
  • 迭代
  • 枚举比较(后两种不适用于IntEnum)
  • 允许的枚举成员与属性
  • 枚举的继承限制
  • 序列化
  • Functional API
相关产品与服务
文件存储
文件存储(Cloud File Storage,CFS)为您提供安全可靠、可扩展的共享文件存储服务。文件存储可与腾讯云服务器、容器服务、批量计算等服务搭配使用,为多个计算节点提供容量和性能可弹性扩展的高性能共享存储。腾讯云文件存储的管理界面简单、易使用,可实现对现有应用的无缝集成;按实际用量付费,为您节约成本,简化 IT 运维工作。
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档