Python 3.7

enum - गणना के लिए सहायता




python

enum - गणना के लिए सहायता

संस्करण 3.4 में नया।

स्रोत कोड: Lib/enum.py

एक प्रतिज्ञान अद्वितीय, निरंतर मूल्यों के लिए प्रतीकात्मक नामों (सदस्यों) का एक सेट है। एक गणना के भीतर, सदस्यों की पहचान के द्वारा तुलना की जा सकती है, और गणना के आधार पर स्वयं को पुनरावृत्त किया जा सकता है।

मॉड्यूल सामग्री

यह मॉड्यूल चार गणना वर्गों को परिभाषित करता है जिनका उपयोग नामों और मूल्यों के अनूठे सेटों को परिभाषित करने के लिए किया जा सकता है: Enum , IntEnum , Flag , और IntFlag । यह एक डेकोरेटर, unique() , और एक सहायक, auto को भी परिभाषित करता है।

class enum.Enum

प्रगणित स्थिरांक बनाने के लिए आधार वर्ग। वैकल्पिक निर्माण सिंटैक्स के लिए अनुभाग कार्यात्मक एपीआई देखें।

class enum.IntEnum

प्रगणित स्थिरांक बनाने के लिए आधार वर्ग जो int उपवर्ग भी हैं।

class enum.IntFlag

प्रगणित स्थिरांक बनाने के लिए बेस क्लास जो कि IntFlag सदस्यता को खोए बिना IntFlag ऑपरेटरों का उपयोग करके जोड़ा जा सकता है। IntFlag सदस्य भी int उपवर्ग हैं।

class enum.Flag

प्रगणित स्थिरांक बनाने के लिए आधार वर्ग जो कि अपने Flag सदस्यता को खोए बिना बिटवाइज़ ऑपरेशंस का उपयोग करके जोड़ा जा सकता है।

enum.unique()

Enum क्लास डेकोरेटर जो केवल एक नाम को सुनिश्चित करता है वह किसी भी एक मूल्य के लिए बाध्य है।

class enum.auto

उदाहरणों को एनम सदस्यों के लिए एक उचित मूल्य के साथ बदल दिया जाता है।

संस्करण 3.6 में नया: Flag , IntFlag , auto

एक एनम बनाना

Enumerations को class सिंटैक्स का उपयोग करके बनाया जाता है, जिससे उन्हें पढ़ना और लिखना आसान हो जाता है। एक वैकल्पिक निर्माण विधि कार्यात्मक एपीआई में वर्णित है। एन्यूमरेशन को परिभाषित करने के लिए, Enum को निम्न प्रकार से Enum :

>>> from enum import Enum
>>> class Color(Enum):
...     RED = 1
...     GREEN = 2
...     BLUE = 3
...

ध्यान दें

Enum सदस्य मान

सदस्य मान कुछ भी हो सकते हैं: int , str , etc .. यदि सटीक मान महत्वहीन है तो आप auto इंस्टेंस का उपयोग कर सकते हैं और आपके लिए एक उचित मूल्य चुना जाएगा। यदि आप अन्य मूल्यों के साथ auto मिक्स करते हैं तो देखभाल की जानी चाहिए।

ध्यान दें

शब्दावली

  • क्लास Color एक एन्यूमरेशन (या एनम ) है
  • Color.RED , Color.GREEN , इत्यादि विशेषताएँ गणन सदस्य (या Color.GREEN सदस्य ) हैं और कार्यात्मक रूप से स्थिर हैं।
  • Enum सदस्यों के नाम और मान हैं ( Color.RED का नाम RED , Color.BLUE का मूल्य है। Color.BLUE 3 , आदि)

ध्यान दें

भले ही हम Enums बनाने के लिए class वाक्य रचना का उपयोग करते हैं, Enums सामान्य पायथन कक्षाएं नहीं हैं। देखें कि एनम अलग कैसे हैं? अधिक जानकारी के लिए।

गणन के सदस्यों के पास मानव पठनीय स्ट्रिंग प्रतिनिधित्व है:

>>> print(Color.RED)
Color.RED

... जबकि उनके repr में अधिक जानकारी है:

>>> print(repr(Color.RED))
<Color.RED: 1>

एन्यूमरेशन सदस्य का प्रकार वह एन्यूमरेशन है जो इसका है:

>>> type(Color.RED)
<enum 'Color'>
>>> isinstance(Color.GREEN, Color)
True
>>>

Enum के सदस्यों के पास एक संपत्ति भी होती है जिसमें सिर्फ उनका आइटम नाम होता है:

>>> print(Color.RED.name)
RED

गणना परिभाषा क्रम में पुनरावृत्ति का समर्थन करती है:

>>> class Shake(Enum):
...     VANILLA = 7
...     CHOCOLATE = 4
...     COOKIES = 9
...     MINT = 3
...
>>> for shake in Shake:
...     print(shake)
...
Shake.VANILLA
Shake.CHOCOLATE
Shake.COOKIES
Shake.MINT

गणन सदस्य धोने योग्य होते हैं, इसलिए उनका उपयोग शब्दकोशों और सेटों में किया जा सकता है:

>>> apples = {}
>>> apples[Color.RED] = 'red delicious'
>>> apples[Color.GREEN] = 'granny smith'
>>> apples == {Color.RED: 'red delicious', Color.GREEN: 'granny smith'}
True

गणन सदस्यों और उनकी विशेषताओं के लिए प्रोग्रामेटिक पहुंच

कभी-कभी प्रोग्राम में सदस्यों तक पहुंचने के लिए यह उपयोगी है (यानी कि जहां Color.RED नहीं करेंगे क्योंकि सटीक रंग प्रोग्राम-राइटिंग के समय ज्ञात नहीं है)। Enum ऐसी अनुमति देता है:

>>> Color(1)
<Color.RED: 1>
>>> Color(3)
<Color.BLUE: 3>

यदि आप नाम से सदस्यों का उपयोग करना चाहते हैं, तो आइटम एक्सेस का उपयोग करें:

>>> Color['RED']
<Color.RED: 1>
>>> Color['GREEN']
<Color.GREEN: 2>

यदि आपके पास कोई एनम सदस्य है और उसके name या value :

>>> member = Color.RED
>>> member.name
'RED'
>>> member.value
1

डुप्लिकेटिंग एनम सदस्यों और मूल्यों

समान नाम वाले दो ईमू सदस्य अमान्य हैं:

>>> class Shape(Enum):
...     SQUARE = 2
...     SQUARE = 3
...
Traceback (most recent call last):
...
TypeError: Attempted to reuse key: 'SQUARE'

हालाँकि, दो enum सदस्यों को समान मान रखने की अनुमति है। दो सदस्यों ए और बी को एक ही मूल्य (और पहले परिभाषित) के साथ देखते हुए, बी ए के लिए एक अन्य नाम है। ए और बी के मूल्य के मूल्य-निर्धारण लुकअप ए। बी का नाम लुकअप भी वापस आ जाएगा:

>>> class Shape(Enum):
...     SQUARE = 2
...     DIAMOND = 1
...     CIRCLE = 3
...     ALIAS_FOR_SQUARE = 2
...
>>> Shape.SQUARE
<Shape.SQUARE: 2>
>>> Shape.ALIAS_FOR_SQUARE
<Shape.SQUARE: 2>
>>> Shape(2)
<Shape.SQUARE: 2>

ध्यान दें

पहले से परिभाषित विशेषता (एक अन्य सदस्य, एक विधि, आदि) के रूप में एक ही नाम के साथ एक सदस्य बनाने का प्रयास या एक सदस्य के रूप में एक ही नाम के साथ एक विशेषता बनाने की कोशिश करने की अनुमति नहीं है।

अद्वितीय गणना मूल्यों को सुनिश्चित करना

डिफ़ॉल्ट रूप से, एन्यूमरेशन एकाधिक नामों को समान मान के लिए उपनाम के रूप में अनुमति देता है। जब यह व्यवहार वांछित नहीं होता है, तो निम्न डेकोरेटर का उपयोग यह सुनिश्चित करने के लिए किया जा सकता है कि प्रत्येक मूल्य का उपयोग केवल एक बार एन्यूमरेशन में किया जाए:

@enum.unique

एक class सज्जाकार विशेष रूप से गणना के लिए। यह एक खोज के __members__ को किसी भी उपनाम को इकट्ठा करके खोजता है; यदि कोई पाया जाता है, तो मूल्य विवरण के साथ उठाया जाता है:

>>> from enum import Enum, unique
>>> @unique
... class Mistake(Enum):
...     ONE = 1
...     TWO = 2
...     THREE = 3
...     FOUR = 3
...
Traceback (most recent call last):
...
ValueError: duplicate values found in <enum 'Mistake'>: FOUR -> THREE

स्वचालित मूल्यों का उपयोग करना

यदि सटीक मान महत्वहीन है तो आप auto उपयोग कर सकते हैं:

>>> from enum import Enum, auto
>>> class Color(Enum):
...     RED = auto()
...     BLUE = auto()
...     GREEN = auto()
...
>>> list(Color)
[<Color.RED: 1>, <Color.BLUE: 2>, <Color.GREEN: 3>]

मान _generate_next_value_() द्वारा चुने जाते हैं, जिन्हें ओवरराइड किया जा सकता है:

>>> class AutoName(Enum):
...     def _generate_next_value_(name, start, count, last_values):
...         return name
...
>>> class Ordinal(AutoName):
...     NORTH = auto()
...     SOUTH = auto()
...     EAST = auto()
...     WEST = auto()
...
>>> list(Ordinal)
[<Ordinal.NORTH: 'NORTH'>, <Ordinal.SOUTH: 'SOUTH'>, <Ordinal.EAST: 'EAST'>, <Ordinal.WEST: 'WEST'>]

ध्यान दें

डिफ़ॉल्ट _generate_next_value_() विधियों का लक्ष्य अगले int साथ अनुक्रम में अगले int प्रदान करने के लिए है, लेकिन जिस तरह से यह करता है वह एक कार्यान्वयन विवरण है और बदल सकता है।

यात्रा

एक enum के सदस्यों पर फेरबदल उपनाम प्रदान नहीं करता है:

>>> list(Shape)
[<Shape.SQUARE: 2>, <Shape.DIAMOND: 1>, <Shape.CIRCLE: 3>]

विशेष विशेषता __members__ को एक आदेशित शब्दकोश मानचित्रण नाम है। इसमें संलयन में परिभाषित सभी नाम शामिल हैं, जिसमें उपनाम भी शामिल हैं:

>>> for name, member in Shape.__members__.items():
...     name, member
...
('SQUARE', <Shape.SQUARE: 2>)
('DIAMOND', <Shape.DIAMOND: 1>)
('CIRCLE', <Shape.CIRCLE: 3>)
('ALIAS_FOR_SQUARE', <Shape.SQUARE: 2>)

__members__ विशेषता का उपयोग गणन सदस्यों के लिए विस्तृत प्रोग्रामेटिक एक्सेस के लिए किया जा सकता है। उदाहरण के लिए, सभी उपनामों को खोजना:

>>> [name for name, member in Shape.__members__.items() if member.name != name]
['ALIAS_FOR_SQUARE']

तुलना

गणना सदस्यों की पहचान से की जाती है:

>>> Color.RED is Color.RED
True
>>> Color.RED is Color.BLUE
False
>>> Color.RED is not Color.BLUE
True

गणना मूल्यों के बीच क्रमबद्ध तुलना का समर्थन नहीं किया जाता है। IntEnum सदस्य पूर्णांक नहीं हैं (लेकिन नीचे IntEnum देखें):

>>> Color.RED < Color.BLUE
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: '<' not supported between instances of 'Color' and 'Color'

समानता की तुलना हालांकि परिभाषित की जाती है:

>>> Color.BLUE == Color.RED
False
>>> Color.BLUE != Color.RED
True
>>> Color.BLUE == Color.BLUE
True

गैर-गणना मूल्यों के खिलाफ तुलना हमेशा बराबर नहीं होगी (फिर से, IntEnum को स्पष्ट रूप से अलग व्यवहार करने के लिए डिज़ाइन किया गया था, नीचे देखें):

>>> Color.BLUE == 2
False

गणना के सदस्यों और विशेषताओं की अनुमति दी

ऊपर के उदाहरण गणना मूल्यों के लिए पूर्णांक का उपयोग करते हैं। पूर्णांकों का उपयोग करना छोटा और आसान है (और कार्यात्मक एपीआई द्वारा डिफ़ॉल्ट रूप से प्रदान किया गया है ), लेकिन सख्ती से लागू नहीं किया गया है। अधिकांश उपयोग-मामलों में, किसी को इस बात की परवाह नहीं है कि गणना का वास्तविक मूल्य क्या है। लेकिन अगर मूल्य महत्वपूर्ण है, तो गणना में मनमाने मूल्य हो सकते हैं।

गणना पायथन कक्षाएं हैं, और हमेशा की तरह तरीके और विशेष तरीके हो सकते हैं। यदि हमारे पास यह गणना है:

>>> class Mood(Enum):
...     FUNKY = 1
...     HAPPY = 3
...
...     def describe(self):
...         # self is the member here
...         return self.name, self.value
...
...     def __str__(self):
...         return 'my custom str! {0}'.format(self.value)
...
...     @classmethod
...     def favorite_mood(cls):
...         # cls here is the enumeration
...         return cls.HAPPY
...

फिर:

>>> Mood.favorite_mood()
<Mood.HAPPY: 3>
>>> Mood.HAPPY.describe()
('HAPPY', 3)
>>> str(Mood.FUNKY)
'my custom str! 1'

अनुमति दी गई नियम निम्नानुसार हैं: एकल अंडरस्कोर के साथ शुरू और समाप्त होने वाले नाम एनम द्वारा आरक्षित हैं और उनका उपयोग नहीं किया जा सकता है; एक गणना के भीतर परिभाषित अन्य सभी विशेषताएँ इस गणना के सदस्य बन जाएँगी, विशेष विधियों ( __str__() , __add__() , आदि) के अपवाद के साथ, डिस्क्रिप्टर (विधियां भी वर्णनकर्ता हैं), और _ignore_ में सूचीबद्ध चर नाम।

नोट: यदि आपका एन्यूमरेशन __new__() और / या __init__() __new__() को परिभाषित करता है, तो __new__() सदस्य को जो भी मूल्य दिए गए थे, वे उन तरीकों में पारित हो जाएंगे। एक उदाहरण के लिए Planet देखें।

प्रतिबंधित Enum उपवर्ग

एक नए Enum वर्ग में एक आधार Enum वर्ग, एक ठोस डेटा प्रकार तक, और आवश्यकतानुसार कई object आधारित मिक्सिन कक्षाएं होनी चाहिए। इन आधार वर्गों का क्रम है:

def EnumName([mix-in, ...,] [data-type,] base-enum):
    pass

इसके अलावा, एक एन्यूमरेशन को उप-वर्ग करने की अनुमति केवल तभी दी जाती है, जब एन्यूमरेशन किसी भी सदस्य को परिभाषित नहीं करता है। तो यह निषिद्ध है:

>>> class MoreColor(Color):
...     PINK = 17
...
Traceback (most recent call last):
...
TypeError: Cannot extend enumerations

लेकिन इसकी अनुमति है:

>>> class Foo(Enum):
...     def some_behavior(self):
...         pass
...
>>> class Bar(Foo):
...     HAPPY = 1
...     SAD = 2
...

सदस्यों को परिभाषित करने वाले शत्रुओं के उपवर्गों को आवंटित करने से कुछ महत्वपूर्ण आक्रमणकारियों के प्रकार और उदाहरणों का उल्लंघन होगा। दूसरी ओर, यह समझ में आता है कि गणना के समूह के बीच कुछ सामान्य व्यवहार को साझा करने की अनुमति है। (उदाहरण के लिए OrderedEnum देखें।)

नमकीन बनाना

गणना में अचार डाला जा सकता है और अप्रकाशित किया जा सकता है:

>>> from test.test_enum import Fruit
>>> from pickle import dumps, loads
>>> Fruit.TOMATO is loads(dumps(Fruit.TOMATO))
True

अचार लगाने के लिए सामान्य प्रतिबंध लागू होते हैं: पिकलेबल एनम को एक मॉड्यूल के शीर्ष स्तर में परिभाषित किया जाना चाहिए, क्योंकि अनप्लिकिंग के लिए उन्हें उस मॉड्यूल से आयात करने योग्य होना चाहिए।

ध्यान दें

अचार प्रोटोकॉल संस्करण 4 के साथ अन्य वर्गों में घोंसले के शिकार के लिए आसानी से अचार बनाना संभव है।

यह कल्पना करना __reduce_ex__() है कि Enumeration class में __reduce_ex__() को परिभाषित करके Enum के सदस्यों को कैसे चुना / अप्रकाशित किया जाता है।

कार्यात्मक एपीआई

Enum वर्ग कॉल करने योग्य है, जो निम्नलिखित कार्यात्मक एपीआई प्रदान करता है:

>>> Animal = Enum('Animal', 'ANT BEE CAT DOG')
>>> Animal
<enum 'Animal'>
>>> Animal.ANT
<Animal.ANT: 1>
>>> Animal.ANT.value
1
>>> list(Animal)
[<Animal.ANT: 1>, <Animal.BEE: 2>, <Animal.CAT: 3>, <Animal.DOG: 4>]

इस एपीआई के शब्दार्थ namedtuple मिलते जुलते हैं। Enum को कॉल का पहला तर्क एन्यूमरेशन का नाम है।

दूसरा तर्क गणन सदस्य नामों का स्रोत है। यह नामों का एक व्हाट्सएप-अलग-अलग स्ट्रिंग, नामों का एक क्रम, कुंजी / मूल्य जोड़े के साथ 2-ट्यूपल्स का एक क्रम या मूल्यों के लिए नामों का एक मानचित्रण (जैसे शब्दकोश) हो सकता है। अंतिम दो विकल्प गणना करने के लिए मनमाना मान निर्दिष्ट करने में सक्षम करते हैं; 1 के साथ शुरू होने वाले पूर्णांकों को ऑटो-असाइन करने वाले अन्य लोग (एक अलग मूल्य शुरू करने के लिए start पैरामीटर का उपयोग करें)। Enum से प्राप्त एक नया वर्ग वापस आ गया है। दूसरे शब्दों में, Animal लिए उपरोक्त असाइनमेंट निम्न के बराबर है:

>>> class Animal(Enum):
...     ANT = 1
...     BEE = 2
...     CAT = 3
...     DOG = 4
...

1 को प्रारंभिक संख्या के रूप में डिफ़ॉल्ट करने का कारण और 0 नहीं है, यह है कि 0 बूलियन अर्थों में False है, लेकिन एनम सदस्य सभी True मूल्यांकन करते हैं।

कार्यात्मक एपीआई के साथ बनाई गई नमकीन बनाने की क्रियाओं को मुश्किल किया जा सकता है क्योंकि फ्रेम स्टैक कार्यान्वयन विवरण का उपयोग करने के लिए किया जाता है और यह पता लगाने के लिए कि मॉड्यूल किस मॉड्यूल में बनाया जा रहा है (उदाहरण के लिए यदि आप अलग-अलग मॉड्यूल में उपयोगिता फ़ंक्शन का उपयोग करते हैं तो यह विफल हो जाएगा, और यह भी काम नहीं कर सकता IronPython या Jython पर)। समाधान मॉड्यूल नाम को स्पष्ट रूप से इस प्रकार निर्दिष्ट करना है:

>>> Animal = Enum('Animal', 'ANT BEE CAT DOG', module=__name__)

चेतावनी

यदि module की आपूर्ति नहीं की जाती है, और Enum यह निर्धारित नहीं कर सकता है कि यह क्या है, तो नए Enum सदस्य अयोग्य नहीं होंगे; त्रुटियों को स्रोत के करीब रखने के लिए, अचार को निष्क्रिय कर दिया जाएगा।

नया अचार प्रोटोकॉल 4 भी, कुछ परिस्थितियों में, __qualname__ पर निर्भर करता है, जिस स्थान पर अचार कक्षा को खोजने में सक्षम होगा। उदाहरण के लिए, यदि वैश्विक मानदंड में वर्ग SomeData में उपलब्ध कराया गया था:

>>> Animal = Enum('Animal', 'ANT BEE CAT DOG', qualname='SomeData.Animal')

पूरा हस्ताक्षर है:

Enum(value='NewEnumName', names=<...>, *, module='...', qualname='...', type=<mixed-in class>, start=1)
मूल्य:

नई Enum क्लास अपने नाम के रूप में क्या रिकॉर्ड करेगी।

नाम:

एनम के सदस्य। यह एक व्हाट्सएप या अल्पविराम से अलग स्ट्रिंग हो सकता है (मान 1 पर शुरू होगा जब तक कि अन्यथा निर्दिष्ट न हो):

'RED GREEN BLUE' | 'RED,GREEN,BLUE' | 'RED, GREEN, BLUE'

या नामों का एक सूचनाकर्ता:

['RED', 'GREEN', 'BLUE']

या (नाम, मान) जोड़ियों का एक पुनरावृत्त:

[('CYAN', 4), ('MAGENTA', 5), ('YELLOW', 6)]

या मानचित्रण:

{'CHARTREUSE': 7, 'SEA_GREEN': 11, 'ROSEMARY': 42}
मॉड्यूल:

मॉड्यूल का नाम जहां नई Enum वर्ग पाया जा सकता है।

qualname:

जहां मॉड्यूल नए Enum वर्ग में पाया जा सकता है।

प्रकार:

नए Enum वर्ग में मिश्रण करने के लिए टाइप करें।

शुरु:

यदि केवल नाम पास किए जाते हैं तो गिनती शुरू करने के लिए नंबर।

संस्करण 3.5 में परिवर्तित: प्रारंभ पैरामीटर जोड़ा गया था।

व्युत्पन्न गणनाएँ

IntEnum

Enum की पहली भिन्नता जो प्रदान की गई है वह भी int का एक उपवर्ग है। एक IntEnum सदस्यों की तुलना पूर्णांक से की जा सकती है; विस्तार से, विभिन्न प्रकारों के पूर्णांक गणनाओं को एक दूसरे से तुलना की जा सकती है:

>>> from enum import IntEnum
>>> class Shape(IntEnum):
...     CIRCLE = 1
...     SQUARE = 2
...
>>> class Request(IntEnum):
...     POST = 1
...     GET = 2
...
>>> Shape == 1
False
>>> Shape.CIRCLE == 1
True
>>> Shape.CIRCLE == Request.POST
True

हालाँकि, वे अभी भी मानक Enum गणना की तुलना नहीं कर सकते हैं:

>>> class Shape(IntEnum):
...     CIRCLE = 1
...     SQUARE = 2
...
>>> class Color(Enum):
...     RED = 1
...     GREEN = 2
...
>>> Shape.CIRCLE == Color.RED
False

IntEnum मान अन्य तरीकों से पूर्णांक की तरह व्यवहार करते हैं, IntEnum आप अपेक्षा करेंगे:

>>> int(Shape.CIRCLE)
1
>>> ['a', 'b', 'c'][Shape.CIRCLE]
'b'
>>> [i for i in range(Shape.SQUARE)]
[0, 1]

IntFlag

IntFlag , IntFlag प्रदत्त Enum की अगली विविधता भी int पर आधारित है। IntFlag सदस्यों के अंतर को बिटवाइज़ ऑपरेटरों ((;, ^, ~,) के उपयोग से जोड़ा जा सकता है और परिणाम अभी भी एक IntFlag सदस्य है। हालाँकि, जैसा कि नाम से ही IntFlag है, IntFlag सदस्य int भी उप-वर्ग IntFlag हैं और जहाँ भी int का उपयोग किया जाता है, उसका उपयोग किया जा सकता है। IntFlag सदस्य पर बिट-वार संचालन के अलावा कोई भी ऑपरेशन IntFlag सदस्यता खो देगा।

संस्करण 3.6 में नया।

नमूना IntFlag वर्ग:

>>> from enum import IntFlag
>>> class Perm(IntFlag):
...     R = 4
...     W = 2
...     X = 1
...
>>> Perm.R | Perm.W
<Perm.R|W: 6>
>>> Perm.R + Perm.W
6
>>> RW = Perm.R | Perm.W
>>> Perm.R in RW
True

संयोजनों को नाम देना भी संभव है:

>>> class Perm(IntFlag):
...     R = 4
...     W = 2
...     X = 1
...     RWX = 7
>>> Perm.RWX
<Perm.RWX: 7>
>>> ~Perm.RWX
<Perm.-8: -8>

IntFlag और Enum बीच एक और महत्वपूर्ण अंतर यह है कि अगर कोई झंडे नहीं IntFlag जाते हैं (मूल्य 0 है), तो इसका बूलियन मूल्यांकन False :

>>> Perm.R & Perm.X
<Perm.0: 0>
>>> bool(Perm.R & Perm.X)
False

क्योंकि IntFlag सदस्य भी int उपवर्ग हैं, जिन्हें उनके साथ जोड़ा जा सकता है:

>>> Perm.X | 8
<Perm.8|X: 9>

झंडा

अंतिम भिन्नता Flag IntFlag तरह, Flag सदस्यों को बिटवाइज़ ऑपरेटरों ((|, |, ^, ~) का उपयोग करके जोड़ा जा सकता है। IntFlag विपरीत, उन्हें किसी भी अन्य Flag एन्यूमरेशन और न ही int खिलाफ, और न ही तुलना की जा सकती है। जबकि मूल्यों को सीधे निर्दिष्ट करना संभव है, auto को मूल्य के रूप में उपयोग करने की सिफारिश की जाती है और Flag एक उचित मूल्य का चयन करने दिया जाता है।

संस्करण 3.6 में नया।

IntFlag तरह, यदि Flag सदस्यों के संयोजन से झंडे नहीं IntFlag , तो बूलियन मूल्यांकन False :

>>> from enum import Flag, auto
>>> class Color(Flag):
...     RED = auto()
...     BLUE = auto()
...     GREEN = auto()
...
>>> Color.RED & Color.GREEN
<Color.0: 0>
>>> bool(Color.RED & Color.GREEN)
False

व्यक्तिगत झंडों में ऐसे मान होने चाहिए जो दो (1, 2, 4, 8,…) की शक्तियां हों, जबकि झंडों का संयोजन नहीं होगा:

>>> class Color(Flag):
...     RED = auto()
...     BLUE = auto()
...     GREEN = auto()
...     WHITE = RED | BLUE | GREEN
...
>>> Color.WHITE
<Color.WHITE: 7>

"कोई झंडे सेट" स्थिति को नाम देने से इसकी बूलियन वैल्यू नहीं बदल जाती है:

>>> class Color(Flag):
...     BLACK = 0
...     RED = auto()
...     BLUE = auto()
...     GREEN = auto()
...
>>> Color.BLACK
<Color.BLACK: 0>
>>> bool(Color.BLACK)
False

ध्यान दें

नए कोड के अधिकांश के लिए, Enum और Flag की दृढ़ता से सिफारिश की जाती है, क्योंकि IntEnum और IntFlag एक एन्यूमरेशन के कुछ शब्दार्थ वादों को तोड़ते हैं (पूर्णांकों के लिए तुलनीय होने के नाते, और इस प्रकार अन्य असंबंधित IntFlag लिए ट्रांज़िटिविटी द्वारा)। IntEnum और IntFlag का उपयोग केवल उन मामलों में किया जाना चाहिए जहां Enum और Flag नहीं करेंगे; उदाहरण के लिए, जब पूर्णांक स्थिरांक को एन्यूमरेशन के साथ, या अन्य प्रणालियों के साथ इंटरऑपरेबिलिटी के लिए बदल दिया जाता है।

अन्य लोग

जबकि IntEnum enum मॉड्यूल का हिस्सा है, यह स्वतंत्र रूप से लागू करने के लिए बहुत सरल होगा:

class IntEnum(int, Enum):
    pass

यह दर्शाता है कि समान व्युत्पन्न गणना को कैसे परिभाषित किया जा सकता है; उदाहरण के लिए एक StrEnum जो int बजाय str में मिलाता है।

कुछ िनयम:

  1. जब Enum को IntEnum जाता है, तो मिक्स-इन प्रकार केवल Enum के आधारों के अनुक्रम में पहले प्रकट होने चाहिए, जैसा कि ऊपर दिए गए IntEnum उदाहरण में है।
  2. जबकि Enum में किसी भी प्रकार के सदस्य हो सकते हैं, एक बार जब आप एक अतिरिक्त प्रकार में मिश्रण करते हैं, तो सभी सदस्यों के पास उस प्रकार के मान होने चाहिए, जैसे ऊपर int । यह प्रतिबंध मिक्स-इन्स पर लागू नहीं होता है जो केवल विधियाँ जोड़ते हैं और किसी अन्य डेटा प्रकार जैसे कि int या str को निर्दिष्ट नहीं करते हैं।
  3. जब किसी अन्य डेटा प्रकार को मिलाया जाता है, तो value विशेषता केवल एनम सदस्य के समान नहीं होती है, हालांकि यह समतुल्य है और बराबर की तुलना करेगा।
  4. % -स्टाइल प्रारूपण: %s और %r क्रमशः __str__() वर्ग के __str__() और __repr__() हैं; अन्य कोड (जैसे कि इंटेनम के लिए %i या %h ) एनम सदस्य को इसके मिश्रित प्रकार के रूप में मानते हैं।
  5. स्वरूपित स्ट्रिंग शाब्दिक , str.format() , और format() मिश्रित-प्रकार के __format__() का उपयोग करेगा। यदि Enum class का str या repr() वांछित है, तो !s / !r प्रारूप कोड का उपयोग करें।

दिलचस्प उदाहरण

जबकि Enum , IntEnum , IntFlag , और Flag में अधिकांश उपयोग के मामलों को कवर करने की उम्मीद है, वे इन सभी को कवर नहीं कर सकते। यहां कुछ अलग-अलग प्रकार की गणनाओं के लिए व्यंजनों का उपयोग किया जा सकता है जो सीधे उपयोग किए जा सकते हैं, या किसी के स्वयं के निर्माण के लिए उदाहरण के रूप में।

मूल्यों को स्वीकार करना

कई उपयोग-मामलों में किसी को ध्यान नहीं है कि एक एन्यूमरेशन का वास्तविक मूल्य क्या है। इस प्रकार की सरल गणना को परिभाषित करने के कई तरीके हैं:

  • मूल्य के लिए auto उदाहरणों का उपयोग करें
  • मूल्य के रूप में object उदाहरणों का उपयोग करें
  • मूल्य के रूप में एक वर्णनात्मक स्ट्रिंग का उपयोग करें
  • मूल्य के रूप में एक tuple का उपयोग करें और एक कस्टम मान के साथ tuple को बदलने के लिए एक कस्टम __new__()

इनमें से किसी भी विधि का उपयोग करना उपयोगकर्ता को सूचित करता है कि ये मूल्य महत्वपूर्ण नहीं हैं, और यह भी एक को जोड़ने, हटाने या सदस्यों को फिर से जोड़ने के लिए शेष सदस्यों को फिर से सक्षम करने में सक्षम बनाता है।

जो भी विधि आप चुनते हैं, आपको एक repr() प्रदान करना चाहिए जो (महत्वहीन) मूल्य भी छुपाता है:

>>> class NoValue(Enum):
...     def __repr__(self):
...         return '<%s.%s>' % (self.__class__.__name__, self.name)
...

auto का उपयोग करना

auto का उपयोग करना पसंद करेंगे:

>>> class Color(NoValue):
...     RED = auto()
...     BLUE = auto()
...     GREEN = auto()
...
>>> Color.GREEN
<Color.GREEN>

object का उपयोग करना

object का उपयोग करना ऐसा लगेगा:

>>> class Color(NoValue):
...     RED = object()
...     GREEN = object()
...     BLUE = object()
...
>>> Color.GREEN
<Color.GREEN>

वर्णनात्मक स्ट्रिंग का उपयोग करना

मान के रूप में स्ट्रिंग का उपयोग करना पसंद करेंगे:

>>> class Color(NoValue):
...     RED = 'stop'
...     GREEN = 'go'
...     BLUE = 'too fast!'
...
>>> Color.GREEN
<Color.GREEN>
>>> Color.GREEN.value
'go'

एक कस्टम __new__() का उपयोग करना

ऑटो-नंबरिंग __new__() करना पसंद करेंगे:

>>> class AutoNumber(NoValue):
...     def __new__(cls):
...         value = len(cls.__members__) + 1
...         obj = object.__new__(cls)
...         obj._value_ = value
...         return obj
...
>>> class Color(AutoNumber):
...     RED = ()
...     GREEN = ()
...     BLUE = ()
...
>>> Color.GREEN
<Color.GREEN>
>>> Color.GREEN.value
2

ध्यान दें

__new__() विधि, अगर परिभाषित की जाती है, तो इसका उपयोग __new__() सदस्यों के निर्माण के दौरान किया जाता है; इसके बाद Enum के __new__() द्वारा प्रतिस्थापित किया जाता है, जिसका उपयोग मौजूदा सदस्यों की तलाश के लिए वर्ग निर्माण के बाद किया जाता है।

OrderedEnum

एक आदेशित IntEnum जो IntEnum पर आधारित नहीं है और इसलिए सामान्य IntEnum अपरिवर्तकों को बनाए रखता है (जैसे कि अन्य गणना के लिए तुलनीय नहीं है):

>>> class OrderedEnum(Enum):
...     def __ge__(self, other):
...         if self.__class__ is other.__class__:
...             return self.value >= other.value
...         return NotImplemented
...     def __gt__(self, other):
...         if self.__class__ is other.__class__:
...             return self.value > other.value
...         return NotImplemented
...     def __le__(self, other):
...         if self.__class__ is other.__class__:
...             return self.value <= other.value
...         return NotImplemented
...     def __lt__(self, other):
...         if self.__class__ is other.__class__:
...             return self.value < other.value
...         return NotImplemented
...
>>> class Grade(OrderedEnum):
...     A = 5
...     B = 4
...     C = 3
...     D = 2
...     F = 1
...
>>> Grade.C < Grade.A
True

DuplicateFreeEnum

यदि कोई उपनाम सदस्य बनाने के बजाय एक डुप्लिकेट सदस्य नाम मिला है, तो एक त्रुटि उठाता है:

>>> class DuplicateFreeEnum(Enum):
...     def __init__(self, *args):
...         cls = self.__class__
...         if any(self.value == e.value for e in cls):
...             a = self.name
...             e = cls(self.value).name
...             raise ValueError(
...                 "aliases not allowed in DuplicateFreeEnum:  %r --> %r"
...                 % (a, e))
...
>>> class Color(DuplicateFreeEnum):
...     RED = 1
...     GREEN = 2
...     BLUE = 3
...     GRENE = 2
...
Traceback (most recent call last):
...
ValueError: aliases not allowed in DuplicateFreeEnum:  'GRENE' --> 'GREEN'

ध्यान दें

यह अन्य व्यवहारों को जोड़ने या बदलने के साथ-साथ एलियास को छोड़ने के लिए Enum को उपवर्गित करने के लिए एक उपयोगी उदाहरण है। यदि एकमात्र वांछित परिवर्तन उपनामों को अस्वीकार कर रहा है, तो इसके बजाय unique() डेकोरेटर का उपयोग किया जा सकता है।

ग्रह

यदि __new__() या __init__() को परिभाषित किया जाता है तो __init__() सदस्य का मान उन तरीकों से पारित हो जाएगा:

>>> class Planet(Enum):
...     MERCURY = (3.303e+23, 2.4397e6)
...     VENUS   = (4.869e+24, 6.0518e6)
...     EARTH   = (5.976e+24, 6.37814e6)
...     MARS    = (6.421e+23, 3.3972e6)
...     JUPITER = (1.9e+27,   7.1492e7)
...     SATURN  = (5.688e+26, 6.0268e7)
...     URANUS  = (8.686e+25, 2.5559e7)
...     NEPTUNE = (1.024e+26, 2.4746e7)
...     def __init__(self, mass, radius):
...         self.mass = mass       # in kilograms
...         self.radius = radius   # in meters
...     @property
...     def surface_gravity(self):
...         # universal gravitational constant  (m3 kg-1 s-2)
...         G = 6.67300E-11
...         return G * self.mass / (self.radius * self.radius)
...
>>> Planet.EARTH.value
(5.976e+24, 6378140.0)
>>> Planet.EARTH.surface_gravity
9.802652743337129

समय सीमा

उपयोग में _ignore_ विशेषता दिखाने के लिए एक उदाहरण:

>>> from datetime import timedelta
>>> class Period(timedelta, Enum):
...     "different lengths of time"
...     _ignore_ = 'Period i'
...     Period = vars()
...     for i in range(367):
...         Period['day_%d' % i] = i
...
>>> list(Period)[:2]
[<Period.day_0: datetime.timedelta(0)>, <Period.day_1: datetime.timedelta(days=1)>]
>>> list(Period)[-2:]
[<Period.day_365: datetime.timedelta(days=365)>, <Period.day_366: datetime.timedelta(days=366)>]

एनम अलग कैसे हैं?

Enums में एक कस्टम मेटाक्लास है जो व्युत्पन्न Enum वर्गों और उनके उदाहरणों (सदस्यों) दोनों के कई पहलुओं को प्रभावित करता है।

Enum Classes

EnumMeta __contains__() , __dir__() , __iter__() और अन्य विधियाँ प्रदान करने के लिए ज़िम्मेदार है, जो किसी Enum वर्ग के साथ कुछ करने की अनुमति देता है जो एक विशिष्ट वर्ग, जैसे list(Color) या some_enum_var in ColorEnumMeta यह सुनिश्चित करने के लिए ज़िम्मेदार है कि अंतिम Enum वर्ग पर विभिन्न अन्य विधियाँ सही हैं (जैसे __new__() , __getnewargs__() , __str__() और __repr__() )।

एनम सदस्य (उर्फ उदाहरण)

एनम के सदस्यों के बारे में सबसे दिलचस्प बात यह है कि वे एकल हैं। EnumMeta उन सभी को बनाता है जब वह Enum वर्ग का निर्माण कर रहा होता है, और फिर यह सुनिश्चित करने के लिए एक कस्टम __new__() कि कोई भी नया कभी भी केवल मौजूदा सदस्य उदाहरणों को वापस करके __new__() नहीं किया जाता है।

महीन अंक

समर्थित __dunder__ नाम

__members__ का एक OrderedDict member_name : member आइटम। यह केवल कक्षा पर उपलब्ध है।

__new__() , यदि निर्दिष्ट किया गया है, तो __new__() सदस्यों को बनाना और वापस करना होगा; सदस्य के _value_ उचित रूप से सेट करना भी एक बहुत अच्छा विचार है। एक बार सभी सदस्य बन जाने के बाद इसका उपयोग नहीं किया जाता है।

समर्थित _sunder_ नाम

  • _name_ - सदस्य का नाम
  • _value_ - सदस्य का मूल्य; __new__ में सेट / संशोधित किया जा सकता है
  • _missing_ - मान नहीं मिलने पर उपयोग किया जाने वाला लुकअप फ़ंक्शन; ओवरराइड हो सकता है
  • _ignore_ - नामों की एक सूची, या तो एक list() रूप में list() या एक str , जो सदस्यों में परिवर्तित नहीं होगी, और अंतिम वर्ग से हटा दी जाएगी
  • _order_ - पायथन 2/3 कोड में उपयोग किया जाता है ताकि यह सुनिश्चित किया जा सके कि सदस्य क्रम सुसंगत है (वर्गीय विशेषता, वर्ग निर्माण के दौरान हटा दिया गया है)
  • _generate_next_value_ - एक _generate_next_value_ सदस्य के लिए एक उचित मूल्य प्राप्त करने के लिए कार्यात्मक एपीआई और auto द्वारा उपयोग किया जाता है; ओवरराइड हो सकता है

संस्करण 3.6 में नया: _missing_ , _order_ , _generate_next_value_

संस्करण 3.7 में नया: _ignore_

Python 2 / Python 3 कोड को सिंक में रखने में मदद करने के लिए एक _order_ विशेषता प्रदान की जा सकती है। यह गणना के वास्तविक आदेश के खिलाफ जाँच की जाएगी और यदि दोनों मेल नहीं खाते हैं तो एक त्रुटि बढ़ाएँगे:

>>> class Color(Enum):
...     _order_ = 'RED GREEN BLUE'
...     RED = 1
...     BLUE = 3
...     GREEN = 2
...
Traceback (most recent call last):
...
TypeError: member order does not match _order_

ध्यान दें

पायथन 2 कोड में _order_ विशेषता आवश्यक है क्योंकि रिकॉर्ड किए जाने से पहले परिभाषा क्रम खो जाता है।

Enum सदस्य प्रकार

Enum सदस्य उनके Enum वर्ग के उदाहरण हैं, और सामान्यतः EnumClass.member रूप में एक्सेस किए EnumClass.member । कुछ परिस्थितियों में उन्हें EnumClass.member.member रूप में भी एक्सेस किया जा सकता है, लेकिन आपको कभी भी ऐसा नहीं करना चाहिए क्योंकि लुकअप विफल हो सकता है या इससे भी बदतर हो सकता है, जिस Enum सदस्य को आप ढूंढ रहे हैं उसके अलावा कुछ लौटाएं (यह सभी का उपयोग करने का एक और अच्छा कारण है- सदस्यों के लिए बड़े नाम):

>>> class FieldTypes(Enum):
...     name = 0
...     value = 1
...     size = 2
...
>>> FieldTypes.value.size
<FieldTypes.size: 2>
>>> FieldTypes.size.value
2

संस्करण 3.5 में बदला गया।

Enum वर्गों और सदस्यों के बूलियन मूल्य

Enum सदस्य जो गैर- Enum प्रकारों (जैसे int , str , आदि) के साथ मिश्रित होते हैं, का मूल्यांकन मिश्रित प्रकार के नियमों के अनुसार किया जाता है; अन्यथा, सभी सदस्य True रूप में मूल्यांकन करते हैं। अपने स्वयं के Enum के बूलियन मूल्यांकन को सदस्य के मूल्य पर निर्भर करने के लिए अपनी कक्षा में निम्नलिखित जोड़ें:

def __bool__(self):
    return bool(self.value)

Enum classes हमेशा True रूप में मूल्यांकन करती है।

विधियों के साथ कक्षाओं में प्रवेश करें

यदि आप अपनी Enum उपवर्ग अतिरिक्त विधियाँ देते हैं, जैसे ऊपर Planet वर्ग, तो वे विधियाँ सदस्य के dir() में dir() , लेकिन वर्ग की नहीं:

>>> dir(Planet)
['EARTH', 'JUPITER', 'MARS', 'MERCURY', 'NEPTUNE', 'SATURN', 'URANUS', 'VENUS', '__class__', '__doc__', '__members__', '__module__']
>>> dir(Planet.EARTH)
['__class__', '__doc__', '__module__', 'name', 'surface_gravity', 'value']

Flag सदस्यों का मेल

यदि ध्वज के सदस्यों के संयोजन का नाम नहीं दिया गया है, तो repr() में सभी नामित झंडे और सभी नामांकित झंडे शामिल होंगे जो मूल्य में हैं:

>>> class Color(Flag):
...     RED = auto()
...     GREEN = auto()
...     BLUE = auto()
...     MAGENTA = RED | BLUE
...     YELLOW = RED | GREEN
...     CYAN = GREEN | BLUE
...
>>> Color(3)  # named combination
<Color.YELLOW: 3>
>>> Color(7)      # not named combination
<Color.CYAN|MAGENTA|BLUE|YELLOW|GREEN|RED: 7>