草根學Python(十一)枚舉類

前言

雖然沒多少閱讀,但是仍是堅持寫下去。對 Python 感興趣的童鞋能夠加入 Python 學習討論微信羣喔。能夠先加我微信,而後拉進羣。本人微信:python

微信
微信

目錄

草根學Python(十一) 枚舉類
草根學Python(十一) 枚舉類

1、枚舉類的使用

實際開發中,咱們離不開定義常量,當咱們須要定義常量時,其中一個辦法是用大寫變量經過整數來定義,例如月份:微信

JAN = 1
FEB = 2
MAR = 3
...
NOV = 11
DEC = 12複製代碼

固然這樣作簡單快捷,缺點是類型是 int ,而且仍然是變量。app

那有沒有什麼好的方法呢?ide

這時候咱們定義一個 class 類型,每一個常量都是 class 裏面惟一的實例。正好 Python 提供了 Enum 類來實現這個功能以下:學習

#!/usr/bin/env python3
# -*- coding: UTF-8 -*-

from enum import Enum

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

# 遍歷枚舉類型
for name, member in Month.__members__.items():
    print(name, '---------', member, '----------', member.value)

# 直接引用一個常量
print('\n', Month.Jan)複製代碼

輸出的結果以下:ui

Python3 枚舉類型的使用
Python3 枚舉類型的使用

可見,咱們能夠直接使用 Enum 來定義一個枚舉類。上面的代碼,咱們建立了一個有關月份的枚舉類型 Month ,這裏要注意的是構造參數,第一個參數 Month 表示的是該枚舉類的類名,第二個 tuple 參數,表示的是枚舉類的值;固然,枚舉類經過 __members__ 遍歷它的全部成員的方法。注意的一點是 , member.value 是自動賦給成員的 int類型的常量,默認是從 1 開始的。並且 Enum 的成員均爲單例(Singleton),而且不可實例化,不可更改this

2、Enum 的源碼

經過上面的實例能夠知道經過 __members__ 能夠遍歷枚舉類的全部成員。那爲何呢?spa

咱們能夠先來大體看看 Enum 的源碼是如何實現的;Enum 在模塊 enum.py 中,先來看看 Enum 類的片斷3d

class Enum(metaclass=EnumMeta):
    """Generic enumeration. Derive from this class to define new enumerations. """複製代碼

能夠看到,Enum 是繼承元類 EnumMeta 的;再看看 EnumMeta 的相關片斷code

class 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__ 來進行訪問了

3、自定義類型的枚舉

但有些時候咱們須要控制枚舉的類型,那麼咱們能夠 Enum 派生出自定義類來知足這種須要。經過修改上面的例子:

#!/usr/bin/env python3
# -*- coding: UTF-8 -*-
from enum import Enum, unique

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


# @unique 裝飾器能夠幫助咱們檢查保證沒有重複值
@unique
class Month(Enum):
    Jan = 'January'
    Feb = 'February'
    Mar = 'March'
    Apr = 'April'
    May = 'May'
    Jun = 'June'
    Jul = 'July'
    Aug = 'August'
    Sep = 'September '
    Oct = 'October'
    Nov = 'November'
    Dec = 'December'


if __name__ == '__main__':
    print(Month.Jan, '----------',
          Month.Jan.name, '----------', Month.Jan.value)
    for name, member in Month.__members__.items():
        print(name, '----------', member, '----------', member.value)複製代碼

輸出的結果以下:

Python3 自定義類型的枚舉類
Python3 自定義類型的枚舉類

經過上面的例子,能夠知道枚舉模塊定義了具備迭代 (interator) 和比較(comparison) 功能的枚舉類型。 它能夠用來爲值建立明肯定義的符號,而不是使用具體的整數或字符串。

4、枚舉的比較

由於枚舉成員不是有序的,因此它們只支持經過標識(identity) 和相等性 (equality) 進行比較。下面來看看 ==is 的使用:

#!/usr/bin/env python3
# -*- coding: UTF-8 -*-
from enum import Enum


class User(Enum):
    Twowater = 98
    Liangdianshui = 30
    Tom = 12


Twowater = User.Twowater
Liangdianshui = User.Liangdianshui

print(Twowater == Liangdianshui, Twowater == User.Twowater)
print(Twowater is Liangdianshui, Twowater is User.Twowater)

try:
    print('\n'.join(' ' + s.name for s in sorted(User)))
except TypeError as err:
    print(' Error : {}'.format(err))複製代碼

輸出的結果:

False True
False True
 Error : '<' not="" supported="" between="" instances="" of="" 'user'="" and="" 'user'<="" code="">
  
  
  

 複製代碼

能夠看看最後的輸出結果,報了個異常,那是由於大於和小於比較運算符引起 TypeError 異常。也就是 Enum 類的枚舉是不支持大小運算符的比較的。

那麼能不能讓枚舉類進行大小的比較呢?

固然是能夠的,使用 IntEnum 類進行枚舉,就支持比較功能。

#!/usr/bin/env python3
# -*- coding: UTF-8 -*-
import enum


class User(enum.IntEnum):
    Twowater = 98
    Liangdianshui = 30
    Tom = 12


try:
    print('\n'.join(s.name for s in sorted(User)))
except TypeError as err:
    print(' Error : {}'.format(err))複製代碼

看看輸出的結果:

Tom
Liangdianshui
Twowater複製代碼

經過輸出的結果能夠看到,枚舉類的成員經過其值得大小進行了排序。也就是說能夠進行大小的比較。

相關文章
相關標籤/搜索