Python enum的使用总结
Python enum的使用总结
枚举(enumeration)在许多编程语言中常被表示为一种基础的数据结构使用,枚举帮助组织一系列密切相关的成员到同一个群组机制下,一般各种离散的属性都可以用枚举的数据结构定义,比如颜色、季节、国家、时间单位等
在Python中没有内置的枚举方法,起初模仿实现枚举属性的方式是
class Directions:NORTH = 1EAST = 2SOUTH = 3WEST = 4
使用成员
Direction.EAST
Direction.SOUTH
检查成员
>>> print("North的类型:", type(Direction.NORTH))
>>> print(isinstance(Direction.EAST, Direction))
North的类型: <class 'int'>
False
成员NORTH的类型是int,而不是Direction,这个做法只是简单地将属性定义到类中
Python标准库enum实现了枚举属性的功能,接下来介绍enum的在实际工作生产中的用法
为什么要用enum,什么时候使用enum?
enum规定了一个有限集合的属性,限定只能使用集合内的值,明确地声明了哪些值是合法值,,如果输入不合法的值会引发错误,只要是想要从一个限定集合取值使用的方式就可以使用enum来组织值。
enum的定义/声明
from enum import Enumclass Directions(Enum):NORTH = 1EAST = 2SOUTH = 3WEST = 4
使用和类型检查:
>>> Directions.EAST
<Directions.EAST: 2>
>>> Directions.SOUTH
<Directions.SOUTH: 3>
>>> Directions.EAST.name
'EAST'
>>> Directions.EAST.value
2
>>> print("South的类型:", type(Directions.SOUTH))
South的类型: <enum 'Directions'>
>>> print(isinstance(Directions.EAST, Directions))
True
>>>
检查示例South的的类型,结果如期望的是Directions。name和value是两个有用的附加属性。
实际工作中可能会这样使用
fetched_value = 2 # 获取值
if Directions(fetched_value) is Directions.NORTH:...
elif Directions(fetched_value) is Directions.EAST:...
else:...
输入未定义的值时:
>>> Directions(5)
ValueError: 5 is not a valid Directions
遍历成员
>>> for name, value in Directions.__members__.items():
... print(name, value)
...
NORTH Directions.NORTH
EAST Directions.EAST
SOUTH Directions.SOUTH
WEST Directions.WEST
在继承Enum的类中定义方法
可以用于将定义的值转换为获取需要的值
from enum import Enumclass Directions(Enum):NORTH = 1EAST = 2SOUTH = 3WEST = 4def angle(self):right_angle = 90.0return right_angle * (self.value - 1)@staticmethoddef angle_interval(direction0, direction1):return abs(direction0.angle() - direction1.angle())
>>> east = Directions.EAST
>>> print("SOUTH Angle:", east.angle())
SOUTH Angle: 90.0
>>> west = Directions.WEST
>>> print("Angle Interval:", Directions.angle_interval(east, west))
Angle Interval: 180.0
将Enum类属性的值定义为函数或方法
from enum import Enum
from functools import partialdef plus_90(value):return Directions(value).angle + 90class Directions(Enum):NORTH = 1EAST = 2SOUTH = 3WEST = 4PLUS_90 = partial(plus_90)def __call__(self, *args, **kwargs):return self.value(*args, **kwargs)@propertydef angle(self):right_angle = 90.0return right_angle * (self.value - 1)print(Directions.NORTH.angle)
print(Directions.EAST.angle)
south = Directions(3)
print("SOUTH angle:", south.angle)
print("SOUTH angle plus 90: ", Directions.PLUS_90(south.value))
输出:
0.0
90.0
SOUTH angle: 180.0
SOUTH angle plus 90: 270.0
key: 1.将函数方法用partial包起来;2.定义__call__方法。
忽略大小写
class TimeUnit(Enum):MONTH = "MONTH"WEEK = "WEEK"DAY = "DAY"HOUR = "HOUR"MINUTE = "MINUTE"@classmethoddef _missing_(cls, value: str):for member in cls:if member.value == value.upper():return member
print(TimeUnit("MONTH"))
print(TimeUnit("Month"))
继承父类Enum的_missing_方法,在值的比较时将case改为一致即可
输出
TimeUnit.MONTH
TimeUnit.MONTH
自定义异常处理
第一种,执行SomeEnum(“abc”)时想要引发自定义错误,其中"abc"是未定义的属性值
class TimeUnit(Enum):MONTH = "MONTH"WEEK = "WEEK"DAY = "DAY"HOUR = "HOUR"MINUTE = "MINUTE"@classmethoddef _missing_(cls, value: str):raise Exception("Customized exception")print(TimeUnit("MONTH"))
TimeUnit("abc")
输出
TimeUnit.MONTHValueError: 'abc' is not a valid TimeUnit
...
Exception: Customized exception
第二种,执行SomeEnum.__getattr__(“ABC”)时,想要引发自定义错误,其中"ABC"是未定义的属性名称,需要重写一下EnumMeta中的__getattr__方法,然后指定实例Enum对象的的metaclass
from enum import Enum, EnumMeta
from functools import partialclass SomeEnumMeta(EnumMeta):def __getattr__(cls, name: str):value = cls.__members__.get(name.upper()) # (这里name是属性名称,可以自定义固定传入大写(或小写),对应下面的A1是大写)if not value:raise Exception("Customized exception")return valueclass SomeEnum1(Enum, metaclass=SomeEnumMeta):A1 = "123"class SomeEnum2(Enum, metaclass=SomeEnumMeta):A1 = partial(lambda x: x)def __call__(self, *args, **kwargs):return self.value(*args, **kwargs)print(SomeEnum1.__getattr__("A1"))
print(SomeEnum2.__getattr__("a1")("123"))
print(SomeEnum2.__getattr__("B")("123"))
输出
SomeEnum1.A1123...
Exception: Customized exception
enum的进阶用法
Functional APIs
动态创建和修改Enum对象,可以在不修改原定义好的Enum类的情况下,追加修改,这里借用一个说明示例,具体的场景使用案例可以看下面的场景举例
>>> # Create an Enum class using the functional API
... DirectionFunctional = Enum("DirectionFunctional", "NORTH EAST SOUTH WEST", module=__name__)
... # Check what the Enum class is
... print(DirectionFunctional)
... # Check the items
... print(list(DirectionFunctional))
... print(DirectionFunctional.__members__.items())
...
<enum 'DirectionFunctional'>
[<DirectionFunctional.NORTH: 1>, <DirectionFunctional.EAST: 2>, <DirectionFunctional.SOUTH: 3>, <DirectionFunctional.WEST: 4>]
dict_items([('NORTH', <DirectionFunctional.NORTH: 1>), ('EAST', <DirectionFunctional.EAST: 2>), ('SOUTH', <DirectionFunctional.SOUTH: 3>), ('WEST', <DirectionFunctional.WEST: 4>)])
>>> # Create a function and patch it to the DirectionFunctional class
... def angle(DirectionFunctional):
... right_angle = 90.0
... return right_angle * (DirectionFunctional.value - 1)
...
...
... DirectionFunctional.angle = angle
...
... # Create a member and access its angle
... south = DirectionFunctional.SOUTH
... print("South Angle:", south.angle())
...
South Angle: 180.0
注:这里没有使用类直接声明的方式来执行枚举(定义时如果不指定值默认是从1开始的数字,也就相当于NORTH = auto(),auto是enum中的方法),仍然可以在后面为这个动态创建的DirectionFunctional创建方法,这种在运行的过程中修改对象的方法也就是python的monkey patching。
Functional APIs的用处和使用场景举例:
# enum_test.py
from enum import Enumclass Arithmetic(Enum):ADD = "+"SUB = "-"MUL = "*"DIV = "/"
# functional_api_test.py
from enum import EnumDynamicEnum = Enum("Arithmetic", {"MOD": "%"}, module="enum_test", qualname="enum_test.Arithmetic")print(DynamicEnum.MOD)print(eval(f"5 {DynamicEnum.MOD.value} 3"))
Arithmetic.MOD
2
2.使用aenum.extend_enum可以动态修改enum.Enum对象
为enum.Enum类Arithmetic
增加一个指数成员EXP="**"
,且不修改原来的Arithmetic
类的代码块:
# functional_api_test.py
from aenum import extend_enum
from enum_test import Arithmeticextend_enum(Arithmetic, "EXP", "**")
print(Arithmetic, list(Arithmetic))
print(eval(f"2 {Arithmetic.EXP.value} 3"))
<enum 'Arithmetic'> [<Arithmetic.ADD: '+'>, <Arithmetic.SUB: '-'>, <Arithmetic.MUL: '*'>, <Arithmetic.DIV: '/'>, <Arithmetic.EXP: '**'>]
8
Python enum的使用总结相关推荐
- boost::python::enum_相关的测试程序
boost::python::enum_相关的测试程序 实现功能 C++实现代码 实现功能 boost::python::enum_相关的测试程序 C++实现代码 #include <boost ...
- python里load什么意思_【python】json中load和loads区别
相同点 dump 和 dumps 都实现了序列化 load 和 loads 都实现反序列化 变量从内存中变成可存储或传输的过程称之为序列化 序列化是将对象状态转化为可保存或可传输格式的过程. 变量内容 ...
- repo:.repo/manifest/default.xml详解
<?xml version="1.0" encoding="UTF-8"?> <manifest> <! -remote 标签指定 ...
- 【Android】Android源码版本
学而不思则罔,思而不学则殆 [Android]Android源码版本 1.下载manifest.git 2.checkout到不同的分支 3.源码下载地址列表 4.Android源码存在的分支 1.下 ...
- 2021-10-22 学习笔记:FastAPI基础使用指南
2021-10-22 学习笔记:FastAPI基础使用指南 已经第三针疫苗了,祝所有人平安! 简单使用 路径参数 查询参数 请求体 查询参数和字符串校验 路径参数和数值校验 请求体参数 请求体 -- ...
- python3.7如何使用enum_我如何用Python表示‘Enum’?
在PEP 435之前,Python没有类似的功能,但是您可以实现自己的. 我自己,我喜欢保持简单(我在网上看到了一些非常复杂的例子),像这样的.class Animal: DOG = 1 CAT = ...
- python之枚举类Enum
常量是任何一门语言中都会使用的一种变量类型 如 要表示星期常量,我们可能会直接定义一组变量 JAN = 1 TWO = 2 ... 然后在返回给前端的时候,我们返回的就会是1,2,...这种魔法数字, ...
- python并且怎么表示_Python-如何在Python中表示“Enum”?
小编典典 如PEP 435中所述,将枚举添加到Python 3.4中.它也已在pypi上反向移植到 3.3.3.2.3.1.2.7.2.6.2.5 和2.4. 对于更高级的Enum技术,请尝试aenu ...
- Python 进阶:enum 模块源码分析
作者:weapon 来源:https://zhuanlan.zhihu.com/p/52056538 起步 上一篇<Python 的枚举类型> (https://zhuanlan.zhih ...
最新文章
- acwing算法题--混合背包问题
- ifstream eof()函数
- java编程赋值运算符_(24)赋值运算符
- python 批量创建变量_Python批量生成和调用变量
- php分页代码 页数太多,php分页函数示例代码分享
- cover-letter
- numpy.mean() in Python
- python中的常量_深入理解Python中的内置常量
- 计算机的进制的转换公式,计算机进制转换公式
- 【CS106】编译原理笔记4 —— 用普遍性泵引理(Pumping lemma)证明语言的正则性
- matlab进行预测误差过大,神经网络预测误差太大怎么办,如何看预测结果
- NTFS,exFAT,FAT32最详细的评测
- mysql的exception_mysqlexception
- 用jQuery实现9宫格抽奖
- 常用颜色RGB、灰度值
- 用计算机进行情报检测属于计算机应用中,[单选] 计算机用于情报检索属于计算机应用中的()。...
- gtbook安装使用教程
- FTP服务器vsftpd安装架设
- Vue打包文件名、默认文件名操作
- 车载传感器技术详解【 持续更新ing 】— 自动驾驶技术概述
热门文章
- 如何在windows上将本地项目上传到Github
- 力软 java主从表保存_JAVA常用知识总结(十二)——数据库(二)
- python设置时间步长与时间离散格式_python怎么定义时间
- Cmd Markdown 编辑阅读器
- 【机器学习】opencv-数据预处理
- MySQL基本指令汇总
- Python3.10 结构化模式匹配 PEP 634
- Kinect深度图与摄像头RGB的标定与配准(转载文章)
- c++学习书籍推荐《超越C++标准库:Boost库导论》下载
- SQL查询优化《三》:少做重复的工作