文章を読んでPythonの列挙を読みます。

8250 ワード

enum は、一意の定数値に結合された記号名のセットであり、反復性と比較可能な特性を有する。enumを使用して、魔法文字列または整数を直接使用するのではなく、定義された識別子を作成することができます。また、開発エンジニアのコードの維持にも便利です。
列挙の作成class文法を使って、列挙の種類を作成してもいいです。読み書きに便利です。また、関数 APIの説明によって定義されています。enumのサブクラスを作成できます。

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など。適切な値が重要でない場合は、autインスタンスを使用して適切な値を選択します。autを他の値と混合する場合は注意が必要です。列挙の種類には、同じ名前のnameは設定できません。同じvalueがあります。enumは属性namevalueを持っています。日常の仕事で一番多く使うのもこの二つの属性です。結果を印刷してみます。

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
列挙の反復
列挙は反復と巡回の順序をサポートします。例を挙げます

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
BADREQUST:400
FOBIDDEN:403
NOT_FOUND:404
REQUST_TIMEOUT:408
SERVICE_UNAVAILABLE:500
OTHER:
見ることができますが、エルゴードstatusは、独立したエニュメレート・メンバであり、namevalue の属性を持っています。
また、以下のような形式で列挙することもできます。

for name, member in HttpStatus.__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を使ってもいいです。

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 リストに追加されます。リストが空でない場合、上記の異常情報を破棄します。
リストの自動割り当て
この機能は、列挙を使用する際に、列挙の識別子の意味だけを気にして値を気にしない場合に使用しますが、文字列または整数と混合して使用する必要がある場合は、追加の注意が必要です。以下に公式の例を貼り付けます。

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_ 方法を書き換えるだけでいいです。
列挙の比較
列挙の対象は比較できますが、値の比較はできません。値の比較が必要な場合は、エニュメレート・インテムオブジェクトの継承が必要です。例を挙げます。

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()
上記のテスト例では、2つの継承タイプの異なるエニュメレート・クラスを作成しました。IntEnumを継承した Seasonは値の比較ができますが、Enumを継承したPart は値の比較ができません。
列挙の方法
列挙では、エニュメレート・クラス自体の特有の方法を定義しても良いし、既にベースクラスで定義されている方法を複写してもいいです。例えば、IntEnum Enum __init__, __str__などです。例を挙げます

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)
上記では、エニュメレート・クラスを定義しました。そのうち、__repr__はエニュメレート・タイプです。__hash__方法を定義して、タプルの値に対応します。また、__format__ 方法を複写しました。
印刷方法は効果を見てみます。

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のエニュメレート・クラスは引き継がれますが、引き継がれるエニュメレート・クラスは、メンバーを定義することはできませんが、抽象的な方法を定義することができます。以下の例を示します

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!')
テストケースは完璧に動作できます。最初の方法でTypeErrの異常を投げました。第二の試験方法では、MoreColorはColorを継承し、ColorはShadeを継承し、サブクラスを通じて親クラスのメソッドを呼び出すことができます。
締め括りをつける
このセクションでは、エムモジュールの基礎知識を紹介します。列挙の作成、列挙メンバーと属性の訪問、列挙方法の作成、列挙の継承などが含まれます。新版の中の_グノレ_、_order_、_missingなどは公式サイトの例を学ぶことができます。また、enumのサブタイプIntEnum、IntFlagsなども私たちがよく使うエニュメレーションベースです。ここでは簡単にIntEnumを紹介します。IntFlagsはIntEnumより多くなりました。
コードアドレス
例コード:Python-10-days-day 036
以上は1文でPythonの列挙の詳しい内容を読んで、もっと多いPython列挙の資料に関して私達のその他の関連している文章に注意して下さい!