Python,寫一個簡單的屬於本身的『BaseEnum』類

Why do This

枚舉,做爲管理常量的有效手段之一,在各大主流語言中都有對應的語言級別的語法。可是在 Python 中沒有這個語法,通常來講,你們比較傾向使用『module級別的常量』來處理,這種作法,天然既簡單又粗暴又有效。可是若是須要管理大量常量,在常見的業務系統中,這個特別常見,僅僅使用上面的『三板斧』是有點不夠的。python

來看看 Python 3 標準庫的 enum。嘴上說不要,內心確實很誠實,Python總算是將其加入到語言中了,雖然是以一種庫的形式。首先咱們來看看其使用方式:git

import enum


class DirectionEnum(enum.IntEnum):
    """ 直接繼承IntEnum,這是很常見的需求 """
    UP = 1
    DOWN = 2
    LEFT = 3
    RIGHT = 4


class DirectionEnum2(enum.Enum):
    """ 繼承更加底層的Enum類 讓本身的實現更加靈活 """
    UP = 'UP'
    DOWN = 'DOWN'
    LEFT = 'LEFT'
    RIGHT = 'RIGHT'


if __name__ == '__main__':

    somevalue = 1
    # 1. 第一種使用方式,OK,很符合咱們的使用習慣,而且是work的
    if somevalue == DirectionEnum.UP:
        # 會運行, 猜想是, IntEnum內部作了必定的拆包動做
        print('yes')

    somevalue2 = 'UP'
    # 2. 第一種使用方式,OK,很符合咱們的使用習慣,然而獲得的,卻不是正確結果
    if somevalue2 == DirectionEnum2.UP:
        # 不會運行, 沒有使用 .value
        print('yes2')
    # 3. 第三種使用方式,OK,並非很是符合咱們的習慣,可是,獲得的預期結果是正確的
    if somevalue2 == DirectionEnum2.UP.value:
        # 運行, 使用了 .value
        print('yes2')
複製代碼

從上面咱們能夠看到,若是僅僅是一些 int 類型的枚舉集合,那麼使用 IntEnum 是 OK 的。若是枚舉集合的成分比較複雜,那麼就要使用 Enum,雖然能夠獲得預期的正確結果,可是卻要改改本身的使用習慣,強迫本身打出DirectionEnum2.UP.value這樣的組合。github

然而,做爲腦瓜子很差使的人來講,DirectionEnum2.UP.value這種我很難記住,並且也不符合個人直覺啊,另外,個人大部分場景,只是須要『安安靜靜地使用一個枚舉』而已,看 enum 庫的內部實現,又是元類,又是委託啥的,各類高科技都用上了。因此,咱們就有強大的動力,去適應本身,而不是適應別人。學習

How to do

考慮到咱們的使用場景很是單一 & 簡單,因此就想到了以下實現spa

import functools


class BaseEnum:
 @classmethod
 @functools.lru_cache(maxsize=1024)
    def values(cls):
        d = cls.__dict__

        return [v
                for k, v in d.items()
                if (not k.startswith('_')) and k.isupper()]
複製代碼

而後使用之,這裏咱們經過寫UT的形式去學習使用接口:code

from unittest import TestCase

import py3utils


class DirectionEnum(py3utils.BaseEnum):
    UP = 1
    DOWN = 2
    LEFT = 3
    RIGHT = 4


class TestBaseEnum(TestCase):
    def test_values_is_list(self):
        self.assertTrue(isinstance(DirectionEnum.values(), list))

    def test_values(self):
        e = [1, 2, 3, 4]
        actual = DirectionEnum.values()

        self.assertEqual(e, actual)

    def test_enum(self):
        actual = DirectionEnum.UP
        expected = 1

        self.assertEqual(actual, expected)
複製代碼

Finally

一些平時使用得比較趁手得代碼 snippet,最好積累起來,放入本身特定得代碼倉庫中,之後想起來了,直接複用之便可。好比我, 就將上面得snippets 加入到本身的倉庫中 https://github.com/hezhiming/py3utils,並佐以比較完善的的UT,以備不時之需。:)繼承

相關文章
相關標籤/搜索