python3.7如何使用enum_在 Python 中使用 enum

原因与初衷

首先便是业务代码中会出现巨量的 XXType 之类的东西,业务越复杂,这种东西就越多,它们符合 enum 的基本假定,用 enum 去管理这些常量是很自然的想法。

其次便是 Python 并没有实现 enum 这一抽象手段(其实我极其希望加入这一特性,另一个希望加入的特性是 const )。

常用的做法

方式1:模块级别常量:

这也是标准库和许多流行库的做法,比如:

# direction.py

UP = 1

DOWN = 2

LEFT = 3

RIGHT = 4

复制代码

方式2:使用 enum 库

Python 2 和Python 3 均可使用,Python 3 更是直接变为标准库,从侧面可知道 enum 这种东西的重要性。

典型使用:

import enum

import unittest

class BaseEnum(enum.Enum):

"""一般都会再次封装下, 后文详述原因"""

@classmethod

def values(cls):

"""获取右边value的集合

因为我们经常要用到 xxvalue in xxEnum.values(), 这是我们

封装的原因与初衷

:return:

"""

values = []

for attr in cls:

values.append(attr.value)

return values

class DirectionEnum(BaseEnum):

"""使用"""

UP = 1

DOWN = 2

LEFT = 3

RIGHT = 4

######################### 单元测试 ##########################

class TestBaseEnum(unittest.TestCase):

def test_values(self):

expected = frozenset((DirectionEnum.UP.value, DirectionEnum.DOWN.value,

DirectionEnum.LEFT.value, DirectionEnum.RIGHT.value))

actual = frozenset(DirectionEnum.values())

self.assertSetEqual(expected, actual)

def test_value_in(self):

value = 1

self.assertTrue(value in DirectionEnum.values())

def test_value_equal(self):

value = 1

self.assertTrue(value == DirectionEnum.UP.value)

复制代码

我的做法

上面的几种做法已经覆盖得很全面了,我完全没必要自己再去弄一个丑陋的轮子。

之所以不用方式1,因为 module 对我而言是一个很重要的命名空间,直接把常量挂载在其下面,对我而言是一种浪费。

之所以不用方式2,完全是因为我有点不喜欢 xxvalue == DirectionEnum.UP.value 这种写法(难道不是 xxvalue == DirectionEnum.UP这种写法更加自然吗?)。但是总的来说,enum 库毕竟是大神的作品,而且也实现了 enum 这一概念的的方方面面,我们自然可以放心使用,而且我也推荐使用。:)

我最终还是选择了一种适合自己业务场景的一种使用方式,虽然土,但总还算是 work。

import unittest

import abc

class BaseEnum(abc.ABC):

@abc.abstractclassmethod

def values(cls):

cls_dict = cls.__dict__

return [cls_dict[key]

for key in cls_dict.keys()

if not key.startswith('_') and key.isupper()]

class DirectionEnum(BaseEnum):

UP = 1

DOWN = 2

LEFT = 3

RIGHT = 4

######################## 单元测试 ################################

class TestBaseEnum(unittest.TestCase):

def test_values(self):

expected = frozenset([DirectionEnum.UP, DirectionEnum.DOWN,

DirectionEnum.LEFT, DirectionEnum.RIGHT])

actual = frozenset(DirectionEnum.values())

self.assertSetEqual(expected, actual)

def test_value_in(self):

value = 1

self.assertTrue(value in DirectionEnum.values())

def test_value_equal(self):

value = 1

self.assertTrue(value == DirectionEnum.UP)

复制代码

生产环境中的用法

目录结构一般我会定义如下

app/

constants/

__init__.py 把所有子文件中的 API 导入到package级别, 方便客户端调用

enum_constants.py 所有XXEnum都在这里面, 文件命名不重要, 反正我会提升到package级别

xx_contants.py

复制代码

使用

from constants import DirectionEnum, XXEnum, YYEnum

def func():

if somevalue == DirectionEnum.UP:

# do something

复制代码

总结

其实更加希望在语言级别提供常量管理的常用手段,而不是为了 simple 而 simple(并没有什么意义)。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值