gpt4 book ai didi

一文读懂Python 枚举

转载 作者:qq735679552 更新时间:2022-09-29 22:32:09 24 4
gpt4 key购买 nike

CFSDN坚持开源创造价值,我们致力于搭建一个资源共享平台,让每一个IT人在这里找到属于你的精彩世界.

这篇CFSDN的博客文章一文读懂Python 枚举由作者收集整理,如果你对这篇文章有兴趣,记得点赞哟.

enum 是一组绑定到唯一常数值的符号名称,并且具备可迭代性和可比较性的特性。我们可以使用 enum 创建具有良好定义的标识符,而不是直接使用魔法字符串或整数,也便于开发工程师的代码维护.

创建枚举 。

我们可以使用 class 语法创建一个枚举类型,方便我们进行读写,另外,根据函数 API 的描述定义,我们可以创建一个 enum 的子类,如下:

?
1
2
3
4
5
6
7
8
9
from enum import Enum
 
class HttpStatus(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,日常工作中使用最多的也是这两个属性,我们打印看看结果:

?
1
2
3
4
5
6
print ( 'Member: {}' . format (HttpStatus.OK))        # Member: HttpStatus.OK
print ( 'Member name: {}' . format (HttpStatus.OK.name))   # Member name: OK
print ( 'Member value: {}' . format (HttpStatus.OK.value))  # Member value: 200
print ( repr (HttpStatus.OK))               # <enum 'HttpStatus'>
print ( type (HttpStatus.OK))               # <HttpStatus.OK: 200>
print ( isinstance (HttpStatus.OK, HttpStatus))      # True

枚举迭代 。

枚举支持迭代和遍历顺序。举个例子:

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
from enum import Enum, auto
 
# 创建
class HttpStatus(Enum):
   OK = 200
   BAD_REQUEST = 400
   FORBIDDEN = 403
   NOT_FOUND = 404
   REQUEST_TIMEOUT = 408
   SERVICE_UNAVAILABLE = 500
   OTHER = auto.value
 
# 迭代
for status in HttpStatus:
   print ( '{} : {}' . format (status.name, status.value))

打印结果:

OK : 200 BAD_REQUEST : 400 FORBIDDEN : 403 NOT_FOUND : 404 REQUEST_TIMEOUT : 408 SERVICE_UNAVAILABLE : 500 OTHER : <object object at 0x000002863E1D7B10> 。

可以看出,遍历的每一个 status 是一个独立的枚举成员,拥有 name 和 value 属性.

另外,我们也可以使用如下形式来进行枚举遍历:

?
1
2
for name, member in HttpStatus.__members__.items():
   print ( '{} : {}' . format (name, member))

枚举成员与属性访问 。

通过枚举 value 进行访问,访问需要使用元组()的形式 。

?
1
print (HttpStatus( 200 ))   # HttpStatus.OK

通过枚举 name 进行访问,访问需要使用列表[]的形式 。

?
1
print (HttpStatus[ 'OK' ])   # HttpStatus.OK

将属性赋予另一个 enum 成员 。

?
1
2
number = HttpStatus.OK
print (number)        # HttpStatus.OK

枚举值唯一 。

上面我们创建的枚举类中,value 值是可以重复的,如果我们不想枚举类中的值重复可以是用装饰器 @unique,举例如下:

?
1
2
3
4
5
6
7
8
9
10
11
12
from enum import Enum, unique
 
# 创建
@unique
class HttpStatus(Enum):
   OK = 200
   BAD_REQUEST = 400
   FORBIDDEN = 403
   NOT_FOUND = 404
   REQUEST_TIMEOUT = 408
   SERVICE_UNAVAILABLE = 500
   OTHER = 200

我们运行后,报如下异常:

ValueError: duplicate values found in <enum 'HttpStatus'>: OTHER -> OK 。

我们查看源代码,发现加入此装饰器的枚举类型,unique 方法会将其 __members__.items() 进行遍历,追加到 duplicates 列表中,如果发现列表不为空,则抛出如上异常信息.

枚举自动赋值 。

此功能用于我们在使用枚举时,只在意枚举的标识符的含义而不在意值的情况下,但是如果需要与字符串或整数混合使用就要额外注意。下面贴上官方的示例:

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
import unittest
from enum import auto, Enum
 
class TestEnum(unittest.TestCase):
  
   def test_auto_number( self ):
     class Color(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 )
  
   def test_auto_name( self ):
     class Color(Enum):
       def _generate_next_value_( self , start, count, last):
         return self
  
       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 对象,举个例子:

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
import unittest
from enum import Enum, IntEnum
 
class TestEnum(unittest.TestCase):
   class Season(IntEnum):
     SPRING = 1
     SUMMER = 2
     AUTUMN = 3
     WINTER = 4
 
   def test_comparisons( self ):
     season = self .Season
 
     self .assertEqual(season.SPRING, 1 )
 
     class Part(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__ 等。举个例子:

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
from enum import Enum
 
class Mood(Enum):
   FUNKY = ( 1 , "hello" )
   HAPPY = ( 3 , "world" )
 
   def describe( self ):
     return self .name, self .value
 
   def __init__( self , num, nice):
     self .num = num
     self .nice = nice
 
   def __str__( self ):
     return 'my custom str! {0}' . format ( self .value)
 
   @classmethod
   def favorite_mood( cls ):
     return cls .HAPPY
 
   @property
   def testValue( self ):
     return self .nice + ':' + str ( self .num)

上面我们定义了一个枚举类,其中 value 是一个枚举类型,我们可以定义 __init__ 方法去对应元组中的值,我们也复写了 __str__ 方法.

打印方法看看效果:

?
1
2
3
4
print (Mood.favorite_mood())   # my custom str! (3, 'world')
print (Mood.HAPPY.describe())  # ('HAPPY', (3, 'world'))
print ( str (Mood.FUNKY))     # my custom str! (1, 'hello')
print (Mood.FUNKY.testValue)   # hello:1

从输出结果看,我们自定义和复写的方法都已经成功的应用到了 Mood 类中.

枚举继承 。

不同于 java 中的枚举类, python 中的枚举类是可以被继承的,但是被继承的枚举类规定其不能定义任何成员,但可以定义抽象方法。举例如下:

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
class EnumExtend(unittest.TestCase):
 
   def test_extending( self ):
     class Shade(Enum):
       def shade( self ):
         print ( self .name)
 
     class Color(Shade):
       red = 1
       green = 2
       blue = 3
     with self .assertRaises(TypeError):
       class MoreColor(Color):
         cyan = 4
         magenta = 5
         yellow = 6
 
   def test_extending2( self ):
     class Shade(Enum):
       def shade( self ):
         return self .name
 
     class Color(Shade):
       def hex ( self ):
         return '%s nice!' % self .value
 
     class MoreColor(Color):
       cyan = 4
       magenta = 5
       yellow = 6
     self .assertEqual(MoreColor.magenta.shade(), 'magenta' )
     self .assertEqual(MoreColor.magenta. hex (), '5 nice!' )

测试用例可以完美运行,我们可以发现:第一个方法中,抛出了 TypeError 的异常;第二个测试方法中,MoreColor 继承了 Color, Color 继承了 Shade, 并且我们可以通过子类调用父类中的方法.

总结 。

本节主要介绍了 enum 模块的基础知识,包含枚举的创建、枚举成员和属性的访问、枚举方法的创建、枚举的继承等。其中新版中的 _ignore_、_order_、_missing_ 等可以学习官网的例子,另外 enum 的子类 IntEnum、IntFlag等也是我们比较常用的枚举基类,本文中简单的介绍了 IntEnum, 而 IntFlag 相比与 IntEnum 多了 &, |, ^, ~ 的操作,其他的子类大家感兴趣也可以了解.

代码地址 。

示例代码:Python-100-days-day036 。

以上就是一文读懂Python 枚举的详细内容,更多关于Python 枚举的资料请关注我其它相关文章! 。

原文链接:http://www.justdopython.com/2019/10/09/python-enum-033/ 。

最后此篇关于一文读懂Python 枚举的文章就讲到这里了,如果你想了解更多关于一文读懂Python 枚举的内容请搜索CFSDN的文章或继续浏览相关文章,希望大家以后支持我的博客! 。

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com