python十四类实用技巧_Python 系列学习十四:面向对象编程 - 枚举类

前言

打算写一系列文章来记录自己学习 Python 3 的点滴;本章主要介绍 Python 面向对象编程中有关枚举类型的相关内容;

本文为作者的原创作品,转载需注明出处;

Enum

Python 通过内置 class Enum,来实现 Python 中的枚举特性;构造枚举类有两种方式,一种是直接使用 Enum 构造函数的方式,一种是使用继承 Enum 自定义枚举类的方式;下面,我们以一年的十二个月份为例子,来看看相关的枚举类型是如何在 Python 中所定义的;

使用 Enum 构造函数

简单的源码分析

先来大致看看 Enum 的源码是如何实现的;Enum 在模块 enum.py 中,先来看看 Enum 类的片段

1

2

3

4

5

6class Enum(metaclass=EnumMeta):

"""Generic enumeration.

Derive from this class to define new enumerations.

"""

可以看到,Enum 是继承元类 EnumMeta 的;再看看 EnumMeta 的相关片段

1

2

3

4

5

6

7

8

9

10

11class EnumMeta(type):

"""Metaclass for Enum"""

@property

def __members__(cls):

"""Returns a mapping of member name->value.

This mapping lists all enum members, including aliases. Note that this

is a read-only view of the internal mapping.

"""

return MappingProxyType(cls._member_map_)

首先__members__方法返回的是一个包含一个Dict既 Map 的 MappingProxyType,并且通过 @property 将方法__members__(cls)的访问方式改变为了变量的的形式,既可以直接通过__members__来进行访问了;

构造一个 Enum

如何构造1

2>>>from enum import Enum

>>>M = Enum('Month', ('Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec'))

通过上述的两行代码,我们就创建了一个有关月份的枚举类型Month,这里要注意的是构造参数,第一个参数Month表示的是该枚举类的类名,第二个 tuple 参数,表示的是枚举类的值;那么,看看我们如何对其取值以及背后的逻辑;

如何取值遍历所有值

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15>>>for key, member in M.__members__.items():

... print( key, '=>', member, ',', member.value, ',', type(member) )

...

Jan => Month.Jan , 1 ,

Feb => Month.Feb , 2 ,

Mar => Month.Mar , 3 ,

Apr => Month.Apr , 4 ,

May => Month.May , 5 ,

Jun => Month.Jun , 6 ,

Jul => Month.Jul , 7 ,

Aug => Month.Aug , 8 ,

Sep => Month.Sep , 9 ,

Oct => Month.Oct , 10 ,

Nov => Month.Nov , 11 ,

Dec => Month.Dec , 12 ,

首先,M.__members__.items() 中所包含的每个元素 item 是什么?

我们来分析一下上述的代码,正如简单的源码分析中我们知道Month.__members__返回的是一个包含Dict的 MappingProxyType 对象,通过调用其 items() 方法既可以返回该Dict,从上述执行的结果中,我们不难分析出该Dict的组成结构是 这样的结构,key 就是对应的月份的名称,value 对应的是一个 member 对象,可以通过 member.value 获取 int 排序值;所以,综上所述,一个 item 既是上述Dict的一个键值对,键是月份的名称,值是一个 member 对象;

再次,那么member又是指的是什么呢?

通过上述的输出结果,我们不难发现,member就是一个Enum对象;

取某个固定值

根据 Key 进行取值,取得的是一个Enum对象;

1

2

3

4

5

6

7

8>>>Jan = M.Jan

>>>print(Jan)

Month.Jan

>>>Jan = M['Jan']

>>>print(Jan)

Month.Jan

>>>print(Jan.value)

1

得到的是一个Enum类型的对象

1

2>>>type(Jan)

根据 Enum.value 进行取值,取得是一个Enum对象

1

2

3>>>Feb = Month(12)

>>>Feb

取值的时候,注意不能越界,否则报错;

1

2

3

4

5

6

7

8

9

10>>>Month(13)

Traceback (most recent call last):

File "", line 1, in

File "/Library/Frameworks/Python.framework/Versions/3.6/lib/python3.6/enum.py", line 291, in __call__

return cls.__new__(cls, value)

File "/Library/Frameworks/Python.framework/Versions/3.6/lib/python3.6/enum.py", line 533, in __new__

return cls._missing_(value)

File "/Library/Frameworks/Python.framework/Versions/3.6/lib/python3.6/enum.py", line 546, in _missing_

raise ValueError("%r is not a valid %s" % (value, cls.__name__))

ValueError: 13 is not a valid Month

继承 Enum 自定义枚举类

那么,除了使用内置的 Enum 对象来构造枚举类型以外,我们该如何自定义自己的枚举类呢?同样以月份为例子,这次我们来构建自己的枚举类型,

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16from enum import Enum, unique

@unique

class Month(Enum):

Jan = 1

Feb = 2

Mar = 3

Apr = 4

May = 5

Jun = 6

Jul = 7

Aug = 8

Sep = 9

Oct = 10

Nov = 11

Dec = 12

是的,自定义构造一个枚举类就是那么简单,看看其调用逻辑,循环取得所有值,

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15>>>for name, member in Month.__members__.items():

... print(name, '=>', member, ',', member.value)

...

Jan => Month.Jan , 1

Feb => Month.Feb , 2

Mar => Month.Mar , 3

Apr => Month.Apr , 4

May => Month.May , 5

Jun => Month.Jun , 6

Jul => Month.Jul , 7

Aug => Month.Aug , 8

Sep => Month.Sep , 9

Oct => Month.Oct , 10

Nov => Month.Nov , 11

Dec => Month.Dec , 12

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值