一文读懂Python 枚举
enum是一组绑定到唯一常数值的符号名称,并且具备可迭代性和可比较性的特性。我们可以使用enum创建具有良好定义的标识符,而不是直接使用魔法字符串或整数,也便于开发工程师的代码维护。
创建枚举
我们可以使用class语法创建一个枚举类型,方便我们进行读写,另外,根据函数API的描述定义,我们可以创建一个enum的子类,如下:
fromenumimportEnum classHttpStatus(Enum): OK=200 BAD_REQUEST=400 FORBIDDEN=403 NOT_FOUND=404 REQUEST_TIMEOUT=408 SERVICE_UNAVAILABLE=500
注意:枚举属性值可以是任何东西:int,str等。如果确切的值不重要,您可以使用auto实例,并为您选择适当的值。如果您将auto与其他值混合,则必须小心。枚举类型中,不可以设置相同名称的name,可以有相同的value。
enum自带属性name和value,日常工作中使用最多的也是这两个属性,我们打印看看结果:
print('Member:{}'.format(HttpStatus.OK))#Member:HttpStatus.OK
print('Membername:{}'.format(HttpStatus.OK.name))#Membername:OK
print('Membervalue:{}'.format(HttpStatus.OK.value))#Membervalue:200
print(repr(HttpStatus.OK))#
print(type(HttpStatus.OK))#
print(isinstance(HttpStatus.OK,HttpStatus))#True
枚举迭代
枚举支持迭代和遍历顺序。举个例子:
fromenumimportEnum,auto
#创建
classHttpStatus(Enum):
OK=200
BAD_REQUEST=400
FORBIDDEN=403
NOT_FOUND=404
REQUEST_TIMEOUT=408
SERVICE_UNAVAILABLE=500
OTHER=auto.value
#迭代
forstatusinHttpStatus:
print('{}:{}'.format(status.name,status.value))
打印结果:
OK:200
BAD_REQUEST:400
FORBIDDEN:403
NOT_FOUND:404
REQUEST_TIMEOUT:408
SERVICE_UNAVAILABLE:500
OTHER:
可以看出,遍历的每一个status是一个独立的枚举成员,拥有name和value属性。
另外,我们也可以使用如下形式来进行枚举遍历:
forname,memberinHttpStatus.__members__.items():
print('{}:{}'.format(name,member))
枚举成员与属性访问
通过枚举value进行访问,访问需要使用元组()的形式
print(HttpStatus(200))#HttpStatus.OK
通过枚举name进行访问,访问需要使用列表[]的形式
print(HttpStatus['OK'])#HttpStatus.OK
将属性赋予另一个enum成员
number=HttpStatus.OK print(number)#HttpStatus.OK
枚举值唯一
上面我们创建的枚举类中,value值是可以重复的,如果我们不想枚举类中的值重复可以是用装饰器@unique,举例如下:
fromenumimportEnum,unique #创建 @unique classHttpStatus(Enum): OK=200 BAD_REQUEST=400 FORBIDDEN=403 NOT_FOUND=404 REQUEST_TIMEOUT=408 SERVICE_UNAVAILABLE=500 OTHER=200
我们运行后,报如下异常:
ValueError:duplicatevaluesfoundin
:OTHER->OK
我们查看源代码,发现加入此装饰器的枚举类型,unique方法会将其__members__.items()进行遍历,追加到duplicates列表中,如果发现列表不为空,则抛出如上异常信息。
枚举自动赋值
此功能用于我们在使用枚举时,只在意枚举的标识符的含义而不在意值的情况下,但是如果需要与字符串或整数混合使用就要额外注意。下面贴上官方的示例:
importunittest fromenumimportauto,Enum classTestEnum(unittest.TestCase): deftest_auto_number(self): classColor(Enum): red=auto() blue=auto() green=auto() self.assertEqual(list(Color),[Color.red,Color.blue,Color.green]) self.assertEqual(Color.red.value,1) self.assertEqual(Color.blue.value,2) self.assertEqual(Color.green.value,3) deftest_auto_name(self): classColor(Enum): def_generate_next_value_(self,start,count,last): returnself red=auto() blue=auto() green=auto() self.assertEqual(list(Color),[Color.red,Color.blue,Color.green]) self.assertEqual(Color.red.value,'red') self.assertEqual(Color.blue.value,'blue') self.assertEqual(Color.green.value,'green')
可以发现,使用auto()得到的是整数自增型,如果我们需要别的方式,只需要在我们的枚举类中,重写_generate_next_value_方法。
枚举比较
枚举对象可以进行比较,但是不能进行值比较,如果需要进行值比较则需要枚举对象继承IntEnum对象,举个例子:
importunittest fromenumimportEnum,IntEnum classTestEnum(unittest.TestCase): classSeason(IntEnum): SPRING=1 SUMMER=2 AUTUMN=3 WINTER=4 deftest_comparisons(self): season=self.Season self.assertEqual(season.SPRING,1) classPart(Enum): SPRING=1 CLIP=2 BARREL=3 self.assertNotEqual(Part.SPRING,1) self.assertNotEqual(Part.SPRING,season.SPRING) TestEnum().test_comparisons()
上面的测试例子当中,我们创建了两个继承类型不一样的枚举类,可以看到继承了IntEnum的Season可以进行值的比较,而继承了Enum的Part则不能进行值比较,并且IntEnum类型与Enum类型也不能进行比较,即使属性和值一样。
枚举方法
枚举中可以定义枚举类自身特有的方法,也可以复写一些已经在基类中定义好的方法,比如:__init__,__str__,__repr__,__hash__,__format__等。举个例子:
fromenumimportEnum
classMood(Enum):
FUNKY=(1,"hello")
HAPPY=(3,"world")
defdescribe(self):
returnself.name,self.value
def__init__(self,num,nice):
self.num=num
self.nice=nice
def__str__(self):
return'mycustomstr!{0}'.format(self.value)
@classmethod
deffavorite_mood(cls):
returncls.HAPPY
@property
deftestValue(self):
returnself.nice+':'+str(self.num)
上面我们定义了一个枚举类,其中value是一个枚举类型,我们可以定义__init__方法去对应元组中的值,我们也复写了__str__方法。
打印方法看看效果:
print(Mood.favorite_mood())#mycustomstr!(3,'world')
print(Mood.HAPPY.describe())#('HAPPY',(3,'world'))
print(str(Mood.FUNKY))#mycustomstr!(1,'hello')
print(Mood.FUNKY.testValue)#hello:1
从输出结果看,我们自定义和复写的方法都已经成功的应用到了Mood类中。
枚举继承
不同于java中的枚举类,python中的枚举类是可以被继承的,但是被继承的枚举类规定其不能定义任何成员,但可以定义抽象方法。举例如下:
classEnumExtend(unittest.TestCase): deftest_extending(self): classShade(Enum): defshade(self): print(self.name) classColor(Shade): red=1 green=2 blue=3 withself.assertRaises(TypeError): classMoreColor(Color): cyan=4 magenta=5 yellow=6 deftest_extending2(self): classShade(Enum): defshade(self): returnself.name classColor(Shade): defhex(self): return'%snice!'%self.value classMoreColor(Color): cyan=4 magenta=5 yellow=6 self.assertEqual(MoreColor.magenta.shade(),'magenta') self.assertEqual(MoreColor.magenta.hex(),'5nice!')
测试用例可以完美运行,我们可以发现:第一个方法中,抛出了TypeError的异常;第二个测试方法中,MoreColor继承了Color,Color继承了Shade,并且我们可以通过子类调用父类中的方法。
总结
本节主要介绍了enum模块的基础知识,包含枚举的创建、枚举成员和属性的访问、枚举方法的创建、枚举的继承等。其中新版中的_ignore_、_order_、_missing_等可以学习官网的例子,另外enum的子类IntEnum、IntFlag等也是我们比较常用的枚举基类,本文中简单的介绍了IntEnum,而IntFlag相比与IntEnum多了&,|,^,~的操作,其他的子类大家感兴趣也可以了解。
代码地址
示例代码:Python-100-days-day036
以上就是一文读懂Python枚举的详细内容,更多关于Python枚举的资料请关注毛票票其它相关文章!
声明:本文内容来源于网络,版权归原作者所有,内容由互联网用户自发贡献自行上传,本网站不拥有所有权,未作人工编辑处理,也不承担相关法律责任。如果您发现有涉嫌版权的内容,欢迎发送邮件至:czq8825#qq.com(发邮件时,请将#更换为@)进行举报,并提供相关证据,一经查实,本站将立刻删除涉嫌侵权内容。