පයිතන්හි 'එනුම්' නියෝජනය කරන්නේ කෙසේද?


1143

මම ප්‍රධාන වශයෙන් සී # සංවර්ධකයෙක්, නමුත් මම දැනට පයිතන් හි ව්‍යාපෘතියක වැඩ කරමින් සිටිමි.

පයිතන්හි එනූම් එකකට සමාන වන්නේ කෙසේද?

Answers:


2709

PEP 435 හි විස්තර කර ඇති පරිදි පයිතන් 3.4 වෙත එනූම්ස් එකතු කර ඇත . එය පයිපි මත 3.3, 3.2, 3.1, 2.7, 2.6, 2.5 සහ 2.4 වෙත ආපසු ප්‍රවාහනය කර ඇත.

වඩා දියුණු එනුම් ක්‍රම සඳහා ඇනුම් පුස්තකාලය උත්සාහ කරන්න (2.7, 3.3+, එකම කර්තෘ enum34. කේතය py2 සහ py3 අතර පරිපූර්ණ ලෙස නොගැලපේ, උදා: ඔබට __order__python 2 අවශ්‍ය වේ ).

  • භාවිතා කිරීමට enum34, කරන්න$ pip install enum34
  • භාවිතා කිරීමට aenum, කරන්න$ pip install aenum

ස්ථාපනය කිරීමෙන් enum(අංක නොමැත) සම්පූර්ණයෙන්ම වෙනස් හා නොගැලපෙන අනුවාදයක් ස්ථාපනය කරනු ඇත.


from enum import Enum     # for enum34, or the stdlib version
# from aenum import Enum  # for the aenum version
Animal = Enum('Animal', 'ant bee cat dog')

Animal.ant  # returns <Animal.ant: 1>
Animal['ant']  # returns <Animal.ant: 1> (string lookup)
Animal.ant.name  # returns 'ant' (inverse lookup)

හෝ සමානව:

class Animal(Enum):
    ant = 1
    bee = 2
    cat = 3
    dog = 4

පෙර සංස්කරණ වලදී, එනූම්ස් ඉටු කර ගත හැකි එක් ක්‍රමයක් නම්:

def enum(**enums):
    return type('Enum', (), enums)

එය එසේ භාවිතා කරයි:

>>> Numbers = enum(ONE=1, TWO=2, THREE='three')
>>> Numbers.ONE
1
>>> Numbers.TWO
2
>>> Numbers.THREE
'three'

මෙවැනි දෙයක් සමඟ ඔබට ස්වයංක්‍රීය ගණනය කිරීම් සඳහා පහසුවෙන් සහාය විය හැකිය:

def enum(*sequential, **named):
    enums = dict(zip(sequential, range(len(sequential))), **named)
    return type('Enum', (), enums)

සහ එසේ භාවිතා කරයි:

>>> Numbers = enum('ZERO', 'ONE', 'TWO')
>>> Numbers.ZERO
0
>>> Numbers.ONE
1

අගයන් නැවත නම් බවට පරිවර්තනය කිරීම සඳහා සහාය මේ ආකාරයෙන් එකතු කළ හැකිය:

def enum(*sequential, **named):
    enums = dict(zip(sequential, range(len(sequential))), **named)
    reverse = dict((value, key) for key, value in enums.iteritems())
    enums['reverse_mapping'] = reverse
    return type('Enum', (), enums)

මෙය එම නම සමඟ ඕනෑම දෙයක් නැවත ලියයි, නමුත් එය ඔබේ එනූම්ස් ප්‍රතිදානයෙහි යෙදවීමට ප්‍රයෝජනවත් වේ. ප්‍රතිලෝම සිතියම්කරණය නොපවතී නම් එය KeyError විසි කරයි. පළමු උදාහරණය සමඟ:

>>> Numbers.reverse_mapping['three']
'THREE'

1
මට තේරුම් ගැනීමට නොහැකි විය, ඔවුන් එනුම් (* අනුක්‍රමික, ** නම් කරන ලද) ක්‍රමයේදී ක්වාර්ග්ස් (** නම් කර) සම්මත කළේ ඇයි? කරුණාකර පැහැදිලි කරයි. ක්වාර්ග්ස් නොමැතිව එය ද ක්රියා කරයි. මම එය පරීක්ෂා කළා.
සීනූ එස්

පයිතන් 2 හි ක්‍රියාකාරී ඒපීඑම් (නම, අගයන්) සමඟ අනුකූල වන පරිදි පයිතන් 2 ශ්‍රිතය යාවත්කාලීන කිරීම සතුටක්
bscan

**namedපැරණි අනුවාදයන් සඳහා වන එනුම් ශ්‍රිතයේ var kwargs ( ) යනු අභිරුචි අගයන් සඳහා සහාය වීමයි:enum("blue", "red", "green", black=0)
Aric Araujo

835

PEP 435 ට පෙර, පයිතන්ට සමාන ප්‍රමාණයක් නොතිබුණද ඔබට ඔබේම දෑ ක්‍රියාත්මක කළ හැකිය.

මම එය සරලව තබා ගැනීමට කැමතියි (මම අන්තර්ජාලයේ බිහිසුණු සංකීර්ණ උදාහරණ කිහිපයක් දැක ඇත්තෙමි), මේ වගේ දෙයක් ...

class Animal:
    DOG = 1
    CAT = 2

x = Animal.DOG

Python 3.4 ( PEP 435 ) හි, ඔබට Enum මූලික පන්තිය බවට පත් කළ හැකිය . PEP හි විස්තර කර ඇති අමතර ක්‍රියාකාරිත්වය මෙයින් ඔබට ලැබෙනු ඇත. උදාහරණයක් ලෙස, එනුම් සාමාජිකයන් පූර්ණ සංඛ්‍යා වලින් වෙනස් වන අතර ඒවා a nameසහ a වලින් සමන්විත වේ value.

class Animal(Enum):
    DOG = 1
    CAT = 2

print(Animal.DOG)
# <Animal.DOG: 1>

print(Animal.DOG.value)
# 1

print(Animal.DOG.name)
# "DOG"

ඔබට අගයන් ටයිප් කිරීමට අවශ්‍ය නැතිනම්, පහත දැක්වෙන කෙටිමඟ භාවිතා කරන්න:

class Animal(Enum):
    DOG, CAT = range(2)

Enumක්‍රියාත්මක කිරීම ලැයිස්තු බවට පරිවර්තනය කළ හැකි අතර ඒවා නැවත ක්‍රියාත්මක කළ හැකිය . එහි සාමාජිකයින්ගේ අනුපිළිවෙල ප්‍රකාශන අනුපිළිවෙල වන අතර ඔවුන්ගේ වටිනාකම් සමඟ කිසිදු සම්බන්ධයක් නැත. උදාහරණයක් වශයෙන්:

class Animal(Enum):
    DOG = 1
    CAT = 2
    COW = 0

list(Animal)
# [<Animal.DOG: 1>, <Animal.CAT: 2>, <Animal.COW: 0>]

[animal.value for animal in Animal]
# [1, 2, 0]

Animal.CAT in Animal
# True

51
නැත, එය පන්ති විචල්‍යයකි.
ජෝර්ජ් ෂෝලි

246
පෙරනිමියෙන් පයිතන් ගතිකය. පයිතන් වැනි භාෂාවකින් සම්පාදක-කාලීන ආරක්ෂාව බලාත්මක කිරීමට වලංගු හේතුවක් නොමැත, විශේෂයෙන් කිසිවක් නොමැති විට. තවත් දෙයක් ... හොඳ රටාවක් යහපත් වන්නේ එය නිර්මාණය කළ සන්දර්භය තුළ පමණි. ඔබ භාවිතා කරන මෙවලම් මත පදනම්ව හොඳ රටාවක් ඉක්මවා හෝ සම්පූර්ණයෙන්ම නිෂ් less ල විය හැකිය.
ඇලෙක්සැන්ඩ්‍රු නෙඩෙල්කු

20
@ ලෝන්ග්පොක් ඔබට අගයන් 100 ක් තිබේ නම්, ඔබ අනිවාර්යයෙන්ම යම් වැරැද්දක් කරයි;) මම මගේ එනූම්ස් හා සම්බන්ධ සංඛ්‍යා වලට කැමතියි ... ඒවා ලිවීමට පහසුය (නූල් එදිරිව), දත්ත ගබඩාවක පහසුවෙන් පැවතිය හැකි අතර ඒවාට අනුකූල වේ C / C ++ enum, එය පහසුවෙන් මාර්ෂල් කිරීම සඳහා උපකාරී වේ.
ඇලෙක්සැන්ඩ්‍රු නෙඩෙල්කු

50
මම මෙය භාවිතා කරමි, සංඛ්‍යා ආදේශ කර object()ඇත.
ටෝබු

9
මුල් PEP354 තවදුරටත් ප්‍රතික්ෂේප නොකෙරේ, නමුත් දැන් එය අතික්‍රමණය කර ඇත. PEP435 පයිතන් 3.4 සඳහා සම්මත එනූම් එකතු කරයි. Python.org/dev/peps/pep-0435
පීටර් හැන්සන්

330

මෙන්න එක් ක්‍රියාත්මක කිරීමකි:

class Enum(set):
    def __getattr__(self, name):
        if name in self:
            return name
        raise AttributeError

මෙන්න එහි භාවිතය:

Animals = Enum(["DOG", "CAT", "HORSE"])

print(Animals.DOG)

51
විශිෂ්ටයි. මෙය ඉක්මවා යාමෙන් මෙය තවදුරටත් වැඩිදියුණු කළ හැකි __setattr__(self, name, value)අතර සමහර විට __delattr__(self, name)ඔබ අහම්බෙන් ලිවුවහොත් Animals.DOG = CATඑය නිහ ly ව සාර්ථක නොවනු ඇත.
ජූනාස් පුලක්ක

15
ha ෂාජාපන්: සිත්ගන්නාසුළු නමුත් සාපේක්ෂව මන්දගාමී ය: එක් එක් ප්‍රවේශය සඳහා පරීක්ෂණයක් සිදු කරනු ලැබේ Animals.DOG; තවද, නියතයන්ගේ අගයන් නූල් වන අතර එමඟින් මෙම නියතයන් සමඟ සැසඳීම් පූර්ණ අගයන් ලෙස ඉඩ දී තිබේ නම් වඩා මන්දගාමී වේ.
එරික් ඕ ලෙබිගොට්

3
ha ෂාජාපන්: උදාහරණයක් ලෙස ඇලෙක්සැන්ඩ්‍රූ හෝ මාක්ගේ කෙටි විසඳුම් තරම් මෙම විසඳුම පැහැදිලි නොවන බව මම තර්ක කරමි. එය සිත්ගන්නා විසඳුමකි. :)
එරික් ඕ ලෙබිගොට්

අතිරික්ත ක්‍රමය වෙනුවට setattr()ශ්‍රිතය ඇතුළත __init__()ක්‍රමය භාවිතා කිරීමට මම උත්සාහ කළෙමි __getattr__(). පංතිය එනුම් (වස්තුව): def __init __ (self, enum_string_list): if type (enum_string_list) == list: enum_string_list සඳහා enum_string සඳහා: setattr (self, enum_string, enum_string) වෙනත්: මතු කරන්න AttributeError
හර්ෂිත් ජේවී

8
@ ඇන්ඩ්‍රෙටෙරා: try-exceptබ්ලොක් එකක සාමාජිකත්වය ලබා ගන්නේ කෙසේදැයි ඔබ පරීක්ෂා කරන්නේ කෙසේද ?
bgusach

213

ඔබට සංඛ්‍යාත්මක අගයන් අවශ්‍ය නම්, ඉක්මන්ම ක්‍රමය මෙන්න:

dog, cat, rabbit = range(3)

පයිතන් 3.x හි ඔබට අවසානයේ තරු ලකුණු කළ ස්ථානගත කිරීමක් ද එක් කළ හැකිය, එමඟින් මතකය නාස්ති කිරීමට ඔබට අවශ්‍ය නැතිනම් ගණන් කළ නොහැකි නම් පරාසයේ ඉතිරි සියලු අගයන් පොඟවනු ඇත:

dog, cat, rabbit, horse, *_ = range(100)

1
නමුත් මෙය වැඩි මතකයක් ගතවනු ඇත!
එම්.ජේ

පයිතන් ඉවත් කිරීම සඳහා වන අගයන් ගණන පරීක්ෂා කරනු ඇති බවට තරු ලකුණු කළ ස්ථානයක ලක්ෂ්‍යය මට නොපෙනේ (එබැවින් එය ඔබ වෙනුවෙන් ගණන් කිරීම සිදු කරනු ඇත).
ගේබ්‍රියෙල් ඩෙවිලර්ස්

Ab ගේබ්‍රියෙල් ඩෙවිලර්ස්, පයිතන් විසින් පැවරිය යුතු ටුපල්හි මූලද්‍රව්‍ය ගණන සමඟ නොගැලපීමක් තිබේ නම් ව්‍යතිරේකයක් මතු කරනු ඇතැයි මම සිතමි.
මාර්ක් හැරිසන්

1
ඇත්ත වශයෙන්ම, එය මගේ පරීක්ෂණයෙන් (පයිතන් 2,3) සිදු කරයි, නමුත් එයින් අදහස් කරන්නේ ක්‍රමලේඛකයාගේ ඕනෑම ගණනය කිරීමේ වැරැද්දක් පළමු පරීක්ෂණයෙන් අල්ලා ගනු ඇති බවයි (නිවැරදි ගණනය කරන පණිවිඩයක් සමඟ).
ගේබ්‍රියෙල් ඩෙවිලර්ස්

2
මට ගණන් කරන්න බැහැ. තරු ලකුණු කළ ස්ථාන දරන්නාට මගේ මුදල් නිවැරදි කළ හැකිද?
javadba

133

ඔබ සඳහා හොඳම විසඳුම රඳා පවතින්නේ ඔබේ ව්‍යාජයෙන් ඔබට අවශ්‍ය දේ මතය enum.

සරල enum:

ඔබට විවිධ අයිතම හදුනාගත හැකි නම්enum ලැයිස්තුවක් පමණක් අවශ්‍ය නම් , මාර්ක් හැරිසන් (ඉහළ) ගේ විසඳුම විශිෂ්ටයි:

Pen, Pencil, Eraser = range(0, 3)

මෙය භාවිතා කිරීමෙන් rangeඔබට ඕනෑම ආරම්භක අගයක් සැකසීමට ඉඩ දෙයි :

Pen, Pencil, Eraser = range(9, 12)

ඊට අමතරව, ඔබ ද භාණ්ඩ ගණයට අයිති බව අවශ්ය නම් රුවනයකි යම් ආකාරයේ, එසේ නම් ඔවුන් පන්තියේ ඉස්මතු කරලීම:

class Stationery:
    Pen, Pencil, Eraser = range(0, 3)

Enum අයිතමය භාවිතා කිරීම සඳහා, ඔබට දැන් බහාලුම් නම සහ අයිතමයේ නම භාවිතා කිරීමට අවශ්‍ය වනු ඇත:

stype = Stationery.Pen

සංකීර්ණ enum:

එනුම් දිගු හෝ වඩා සංකීර්ණ භාවිතයන් සඳහා, මෙම විසඳුම් ප්‍රමාණවත් නොවේ. පයිතන් කුක් පොතේ ප්‍රකාශයට පත් කරන ලද පයිතන් හි ගණනය කිරීම් අනුකරණය කිරීම සඳහා විල් වෙයාර් විසින් ඔබට වට්ටෝරුව දෙස බැලිය හැකිය . එහි මාර්ගගත අනුවාදයක් මෙහි ඇත.

වැඩි විස්තර:

PEP 354: පයිතන් හි ගණන් බැලීම්වල පයිතන් හි එනූම් සඳහා වූ යෝජනාවක් සහ එය ප්‍රතික්ෂේප වූයේ මන්ද යන්න පිළිබඳ සිත්ගන්නා තොරතුරු ඇත.


7
සමග rangeඔබ එය 0 වේ නම් පළමු තර්කය පළමුෙවන් හැකි
ToonAlfrink

සමහර අරමුණු වලට ගැලපෙන තවත් ව්‍යාජ එනූම් එකක් වේ my_enum = dict(map(reversed, enumerate(str.split('Item0 Item1 Item2')))). එවිට my_enumබැලීමේදී භාවිතා කළ හැකිය, උදා: my_enum['Item0']අනුපිළිවෙලකට දර්ශකයක් විය හැකිය. str.splitකිසියම් අනුපිටපත් තිබේ නම් ව්‍යතිරේකයක් විසි කරන ශ්‍රිතයක ප්‍රති result ලය එතීමට ඔබට අවශ්‍ය විය හැකිය .
ඇනා නිම්බස්

හොඳයි! කොඩි සඳහා ඔබටFlag1, Flag2, Flag3 = [2**i for i in range(3)]
majkelx

මෙය හොඳම පිළිතුරයි
යූරි පොස්නියැක්

80

ජාවා පූර්ව ජේඩීකේ 5 හි භාවිතා කළ ටයිප්සෙෆ් එනුම් රටාවට වාසි ගණනාවක් ඇත. ඇලෙක්සැන්ඩ්‍රූගේ පිළිතුරට සමානව, ඔබ පන්තියක් නිර්මාණය කරන අතර පන්ති මට්ටමේ ක්ෂේත්‍ර යනු එනුම් අගයන් ය; කෙසේ වෙතත්, එනුම් අගයන් කුඩා නිඛිලවලට වඩා පන්තියේ අවස්ථා වේ. ඔබේ එන්අම් අගයන් නොදැනුවත්වම කුඩා නිඛිලවලට සමාන නොකිරීමේ වාසිය මෙයයි, ඔබට ඒවා මුද්‍රණය කරන ආකාරය පාලනය කළ හැකිය, එය ප්‍රයෝජනවත් නම් අත්තනෝමතික ක්‍රම එකතු කළ හැකිය.

class Animal:
   def __init__(self, name):
       self.name = name

   def __str__(self):
       return self.name

   def __repr__(self):
       return "<Animal: %s>" % self

Animal.DOG = Animal("dog")
Animal.CAT = Animal("cat")

>>> x = Animal.DOG
>>> x
<Animal: dog>
>>> x == 1
False

පයිතන්-දේව් පිළිබඳ මෑත කාලීන නූලක් පෙන්වා දුන්නේ වනයේ එනුම් පුස්තකාල කිහිපයක් ඇති බවයි.


16
මම හිතන්නේ මෙය ඉතා නරක ප්‍රවේශයකි. Animal.DOG = සත්ව ("බල්ලා") Animal.DOG2 = සත්ව ("බල්ලා") Animal.DOG == Animal.DOG2 අසමත් වේ ...
ව්යාකූලත්වය

11
On කොන්ෆියුෂන් පරිශීලකයා ඉදිකිරීම්කරු අමතන්නේ නැත, ඉදිකිරීම්කරුවෙකු පවා සිටීම ක්‍රියාත්මක කිරීමේ විස්තරයක් වන අතර නව ගණනය කිරීම් අගයන් සෑදීමෙන් කිසිදු තේරුමක් නැති බවත් පිටවීමේ කේතය නොපවතින බවත් ඔබේ කේතය භාවිතා කරන්නේ කවුරුන්ද යන්න සන්නිවේදනය කළ යුතුය. "හරි දේ කරන්න". ඇත්ත වශයෙන්ම එය Animal.from_name ("බල්ලා") -> Animal.DOG ක්‍රියාත්මක කිරීමෙන් ඔබව වළක්වන්නේ නැත.
ආරොන් මේන්පා

13
"ඔබේ එනූම් අගයන් නොදැනුවත්වම කුඩා නිඛිලවලට සමාන නොවේ." මෙහි ඇති වාසිය කුමක්ද? ඔබේ එනූමය පූර්ණ සංඛ්‍යා සමඟ සංසන්දනය කිරීමේ වරද කුමක්ද? විශේෂයෙන් ඔබ දත්ත සමුදාය තුළ එනුම් ගබඩා කරන්නේ නම්, ඔබට සාමාන්‍යයෙන් එය පූර්ණ සංඛ්‍යා ලෙස ගබඩා කිරීමට අවශ්‍ය වේ, එබැවින් ඔබට එය යම් අවස්ථාවක දී පූර්ණ සංඛ්‍යා සමඟ සංසන්දනය කිරීමට සිදුවේ.
ibz

3
Aaaaron Maenpaa. නිවැරදි. එය තවමත් එය කිරීමට බිඳුණු හා ඕනෑවට වඩා සංකීර්ණ ක්‍රමයකි.
aaronasterling

4
@AaronMcSmooth එය ඇත්ත වශයෙන්ම රඳා පවතින්නේ ඔබ "එනූම්ස් යනු අඟල් කිහිපයක් සඳහා වූ නම් පමණි" යන සී දෘෂ්ටි කෝණයෙන්ද නැතහොත් එනුම් අගයන් සැබෑ වස්තූන් වන ක්‍රමවේදයන් ඇති වස්තූන් නැඹුරු වූ ප්‍රවේශය මතද යන්න මතය (ජාවා හි එනූම්ස් යනු එලෙසයි 1.5 ක් වන අතර කුමන වර්ගයේ ආරක්ෂිත එනූම් රටාව සඳහාද යන්න) පුද්ගලිකව, මම ස්විච් ප්‍රකාශ වලට කැමති නැත, එබැවින් මම සත්‍ය වස්තු වන එනුම් අගයන් වෙත නැඹුරු වෙමි.
ආරොන් මේන්පා

63

එනුම් පන්තියක් එක් ලයිනර් එකක් විය හැකිය.

class Enum(tuple): __getattr__ = tuple.index

එය භාවිතා කරන්නේ කෙසේද (ඉදිරියට සහ ආපසු හැරවීම, යතුරු, අගයන්, අයිතම ආදිය)

>>> State = Enum(['Unclaimed', 'Claimed'])
>>> State.Claimed
1
>>> State[1]
'Claimed'
>>> State
('Unclaimed', 'Claimed')
>>> range(len(State))
[0, 1]
>>> [(k, State[k]) for k in range(len(State))]
[(0, 'Unclaimed'), (1, 'Claimed')]
>>> [(k, getattr(State, k)) for k in State]
[('Unclaimed', 0), ('Claimed', 1)]

මම හිතන්නේ එය සරලම අවසානය වඩාත් අලංකාර විසඳුමයි. පයිතන් 2.4 හි (ඔව්, පැරණි උරුම සේවාදායකය) ටුපල් දර්ශක නොමැත. මම ලැයිස්තුව වෙනුවට ආදේශ කිරීම විසඳුවා.
මැසිමෝ

මම මෙය ජුපිටර් නෝට්බුක් එකකින් අත්හදා බැලූ අතර එය එක් පේළියේ අර්ථ දැක්වීමක් ලෙස ක්‍රියා නොකරන බව සොයා ගත්තෙමි , නමුත් ගෙටැටර් අර්ථ දැක්වීම දෙවන (ඉන්ඩෙන්ට්) රේඛාවකට දැමීම පිළිගනු ඇත.
user5920660

මෙම විසඳුම inපිළිවෙලට ඇති සාමාජිකයින් සෙවීම සඳහා මූලික පදය භාවිතා කරමු . උදාහරණ භාවිතය:'Claimed' in Enum(['Unclaimed', 'Claimed'])
ෆර්සාඩ් අබ්දොල්සොයිනි

52

ඉතින්, මම එකඟයි. පයිතන් හි වර්ගයේ ආරක්ෂාව බලාත්මක නොකරමු, නමුත් මෝඩ වැරදි වලින් මා ආරක්ෂා කර ගැනීමට කැමැත්තෙමි. ඉතින් අපි මේ ගැන සිතන්නේ කුමක්ද?

class Animal(object):
    values = ['Horse','Dog','Cat']

    class __metaclass__(type):
        def __getattr__(self, name):
            return self.values.index(name)

එය මගේ එනූම්ස් නිර්වචනය කිරීමේදී අගය ision ට්ටනයෙන් වළක්වයි.

>>> Animal.Cat
2

තවත් පහසු වාසියක් ඇත: සැබවින්ම වේගවත් ආපසු හැරවීම්:

def name_of(self, i):
    return self.values[i]

මම මේකට කැමතියි, නමුත් ඔබට කාර්යක්ෂමතාව සඳහා අගයන් අගුලු දැමිය හැකිද? මම එය සමඟ සෙල්ලම් කළ අතර init හි ආග්ස් වලින් ස්වයං අගයන් සැකසෙන අනුවාදයක් ඉදිරිපත් කළෙමි . ප්රකාශ කිරීමට හැකිවීම සතුටක් Animal = Enum('horse', 'dog', 'cat'). ස්වයං වටිනාකම්වල කිසියම් අයිතමයක් අස්ථානගත වී ඇති අවස්ථාවකදී මම getattr හි ValueError අල්ලා ගනිමි - ඒ වෙනුවට සැපයූ නාම නූල සමඟ AttributeError මතු කිරීම වඩා හොඳ බව පෙනේ. එම ප්‍රදේශයේ මගේ සීමිත දැනුම මත පදනම්ව මට පයිතන් 2.7 හි වැඩ කිරීමට මෙටාක්ලාස් ලබා ගත නොහැකි විය, නමුත් මගේ අභිරුචි එනුම් පන්තිය සෘජු උදාහරණ ක්‍රම සමඟ හොඳින් ක්‍රියා කරයි.
trojjer

50

පයිතන්ට සමාන නිමැවුමක් නොමැත enum, සහ වෙනත් පිළිතුරු වලට ඔබේම දෑ ක්‍රියාත්මක කිරීමට අදහස් ඇත ( පයිතන් කුක් පොතේ ඉහළම අනුවාදය ගැනද ඔබ උනන්දු විය හැකිය ).

කෙසේ වෙතත්, enumසී සඳහා කැඳවනු ලබන අවස්ථාවන්හිදී, මම සාමාන්‍යයෙන් අවසන් කරන්නේ සරල නූල් භාවිතා කිරීමෙනි : වස්තූන් / ගුණාංග ක්‍රියාත්මක වන ආකාරය නිසා, (ඇ) පයිතන් කෙසේ හෝ කෙටි නූල් සමඟ ඉතා වේගයෙන් වැඩ කිරීමට ප්‍රශස්තිකරණය කර ඇත. නිඛිල භාවිතා කිරීමෙන් කිසිඳු කාර්ය සාධනයක් නොලැබේ. යතුරු ලියනය / අවලංගු අගයන්ගෙන් ආරක්ෂා වීමට ඔබට තෝරාගත් ස්ථානවල චෙක්පත් ඇතුළත් කළ හැකිය.

ANIMALS = ['cat', 'dog', 'python']

def take_for_a_walk(animal):
    assert animal in ANIMALS
    ...

(පංතියක් භාවිතා කිරීමට සාපේක්ෂව එක් අවාසියක් නම් ඔබට ස්වයං සම්පුර්ණ කිරීමේ ප්‍රතිලාභය අහිමි වීමයි)


2
මම මෙම විසඳුමට කැමතියි. හැකි සෑම තැනකම බිල්ට් වර්ග භාවිතා කිරීමට මම කැමතියි.
සීන් ඔසේවා

එම අනුවාදය සැබවින්ම ඉහළින් නොවේ. එය සතුව සැපයුම් පරීක්ෂණ කේත
රාශියක් ඇත

1
ඇත්ත වශයෙන්ම, "නිවැරදි" අනුවාදය අදහස් දැක්වීම්වල ඇති අතර එය වඩාත් සංකීර්ණ වේ - ප්‍රධාන අනුවාදයේ සුළු දෝෂයක් ඇත.
කේස්බෑෂ්

40

2013-05-10 දින ගයිඩෝ විසින් PEP 435 පයිතන් 3.4 සම්මත පුස්තකාලයට පිළිගැනීමට එකඟ විය . මෙයින් අදහස් කරන්නේ ගණනය කිරීම් සඳහා පයිතන් අවසානයේ බිල්ඩින් සහාය ඇති බවයි!

පයිතන් 3.3, 3.2, 3.1, 2.7, 2.6, 2.5 සහ 2.4 සඳහා පසුපෙළක් ඇත. එය පයිපී හි enum34 ලෙස ඇත .

ප්‍රකාශය:

>>> from enum import Enum
>>> class Color(Enum):
...     red = 1
...     green = 2
...     blue = 3

නිරූපණය:

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

අනුකරණය:

>>> for color in Color:
...   print(color)
...
Color.red
Color.green
Color.blue

ක්‍රමලේඛ ප්‍රවේශය:

>>> Color(1)
Color.red
>>> Color['blue']
Color.blue

වැඩි විස්තර සඳහා , යෝජනාව බලන්න . නිල ලියකියවිලි ඉක්මනින් පැමිණෙනු ඇත.


34

පයිතන් හි එනූම්ස් අර්ථ දැක්වීමට මම කැමතියි:

class Animal:
  class Dog: pass
  class Cat: pass

x = Animal.Dog

නිඛිල අද්විතීය බව සහතික කිරීම ගැන කරදර විය යුතු නැති නිසා (නිඛිල = 1 සහ කැට් = 1 ඔබ ඉස්කුරුප්පු කරනු ඇතැයි පැවසුවහොත්) නිඛිල භාවිතා කිරීමට වඩා එය දෝෂ-සාධනයකි.

ඔබ යතුරු ලියනය ගැන කරදර විය යුතු නැති නිසා එය නූල් භාවිතා කිරීමට වඩා දෝෂ සහගතය (උදා: x == "කැට්" නිහ ly ව අසමත් වේ, නමුත් x == සත්ව.කැට් යනු ධාවන කාල ව්‍යතිරේකයකි).


33
def M_add_class_attribs(attribs):
    def foo(name, bases, dict_):
        for v, k in attribs:
            dict_[k] = v
        return type(name, bases, dict_)
    return foo

def enum(*names):
    class Foo(object):
        __metaclass__ = M_add_class_attribs(enumerate(names))
        def __setattr__(self, name, value):  # this makes it read-only
            raise NotImplementedError
    return Foo()

එය මේ ආකාරයට භාවිතා කරන්න:

Animal = enum('DOG', 'CAT')
Animal.DOG # returns 0
Animal.CAT # returns 1
Animal.DOG = 2 # raises NotImplementedError

ඔබට අද්විතීය සංකේත අවශ්‍ය නම් සහ අගයන් ගැන තැකීමක් නොකරන්නේ නම්, මෙම පේළිය ප්‍රතිස්ථාපනය කරන්න:

__metaclass__ = M_add_class_attribs(enumerate(names))

මේ සමඟ:

__metaclass__ = M_add_class_attribs((object(), name) for name in names)

11
IMHO එය ඔබ වෙනස් නම් පිරිසිදු වනු ඇත enum(names)කිරීමට enum(*names)නම් ඔබ කළ යුතු අමතර වරහන එය කරන විට අතහැර හැකි -.
ක්‍රිස් ලුට්ස්

මම මේ ප්‍රවේශයට කැමතියි. Animal.DOG == 'DOG' යන ලස්සන දේපල ඇති නමට සමාන ගුණාංගයකට නම සැකසීමට මම එය ඇත්ත වශයෙන්ම වෙනස් කළෙමි, එබැවින් ඒවා ස්වයංක්‍රීයව ඔබ වෙනුවෙන් දැඩි වේ. (
නිදොස් කිරීමේ

25

පයිතන් 3.4 සිට එනූම් සඳහා නිල සහාය ලැබේ. පයිතන් 3.4 ප්‍රලේඛන පිටුවෙන් ඔබට ප්‍රලේඛන සහ උදාහරණ සොයාගත හැකිය .

පන්ති සින්ටැක්ස් භාවිතයෙන් ගණන් කිරීම් නිර්මාණය කර ඇති අතර එමඟින් කියවීමට හා ලිවීමට පහසු වේ. විකල්ප API නිර්මාණය කිරීමේ API හි විස්තර කර ඇත. ගණනය කිරීමක් අර්ථ දැක්වීම සඳහා, පහත දැක්වෙන පරිදි උප කාණ්ඩය

from enum import Enum
class Color(Enum):
     red = 1
     green = 2
     blue = 3

පසුපසට ගෙනයාමට දැන් සහය දක්වයි. යා යුතු මාර්ගය මෙයයි.
srock

24

Python දී නිඛිල තවත්, ඉතා සරල, ක්රියාත්මක කිරීම භාවිතා namedtuple:

from collections import namedtuple

def enum(*keys):
    return namedtuple('Enum', keys)(*keys)

MyEnum = enum('FOO', 'BAR', 'BAZ')

හෝ, විකල්පයක් ලෙස,

# With sequential number values
def enum(*keys):
    return namedtuple('Enum', keys)(*range(len(keys)))

# From a dict / keyword args
def enum(**kwargs):
    return namedtuple('Enum', kwargs.keys())(*kwargs.values())




# Example for dictionary param:
values = {"Salad": 20, "Carrot": 99, "Tomato": "No i'm not"} 
Vegetables= enum(**values)

# >>> print(Vegetables.Tomato)        'No i'm not'


# Example for keyworded params: 
Fruits = enum(Apple="Steve Jobs", Peach=1, Banana=2)

# >>> print(Fruits.Apple)             'Steve Jobs'

එම උප පංතියට ඉහළින් ඇති ක්‍රමය මෙන් setමෙයද ඉඩ දෙයි:

'FOO' in MyEnum
other = MyEnum.FOO
assert other == MyEnum.FOO

නමුත් විවිධ යතුරු සහ අගයන් තිබිය හැකි බැවින් වඩා නම්‍යශීලී බවක් ඇත. මෙය ඉඩ දෙයි

MyEnum.FOO < MyEnum.BAR

අනුක්‍රමික සංඛ්‍යා අගයන් පුරවන අනුවාදය ඔබ භාවිතා කරන්නේ නම් අපේක්ෂිත පරිදි ක්‍රියා කිරීමට.


මම මෙම ප්‍රවේශයට වඩාත්ම කැමති වූයේ පහසු සහ පැහැදිලි බැවිනි. එය භාවිතා කිරීමට කැමති අය සඳහා එක් සටහනක් .. collectionsමොඩියුලය collections.abcපයිතන් 3.10 තුළට ගමන් කිරීමට නියමිතය. මෙම මොඩියුලයට ඇතුළත් වූ බවක් නොපෙනේ namedtuple, එබැවින් මොඩියුලය namedtupleතුළ රැඳී සිටීමට ඉඩ ඇතcollections
ලූක් සේව්ෆ්‍රොග්ස්

23

හ්ම් ... මම හිතන්නේ එනූමයකට කිට්ටුම දෙය ශබ්ද කෝෂයක් වනු ඇති අතර එය මේ ආකාරයෙන් අර්ථ දක්වා ඇත:

months = {
    'January': 1,
    'February': 2,
    ...
}

හෝ

months = dict(
    January=1,
    February=2,
    ...
)

එවිට, ඔබට මේ වගේ නියතයන් සඳහා සංකේතාත්මක නම භාවිතා කළ හැකිය:

mymonth = months['January']

ටුපල් ලැයිස්තුවක් හෝ ටුපල් ටුපල් වැනි වෙනත් විකල්ප තිබේ, නමුත් වටිනාකමට ප්‍රවේශ වීම සඳහා “සංකේතාත්මක” (නියත නූල්) ක්‍රමයක් ඔබට සපයන එකම එක ශබ්දකෝෂයයි.

සංස්කරණය කරන්න: මම ඇලෙක්සැන්ඩ්‍රූගේ පිළිතුරටත් කැමතියි!


කොම්බෝ බොක්ස් අයිතම ලෙස පෙනී සිටීමට ඔබට එහි නූල් අගයන් අවශ්‍ය වනවා සේම එහි අගයන්ට ප්‍රවේශ වීමට අවශ්‍ය නම් ඔබට බොහෝ විට ශබ්ද කෝෂයක් මත පහසුවෙන් නැවත යෙදිය හැකිය. එබැවින් ගණනය කිරීම් වෙනුවට ආදේශකයක් ලෙස ශබ්ද කෝෂයක් භාවිතා කරන්න.
LEMUEL ADANE

20

මා භාවිතා කරන දේ:

class Enum(object):
    def __init__(self, names, separator=None):
        self.names = names.split(separator)
        for value, name in enumerate(self.names):
            setattr(self, name.upper(), value)
    def tuples(self):
        return tuple(enumerate(self.names))

භාවිතා කරන්නේ කෙසේද:

>>> state = Enum('draft published retracted')
>>> state.DRAFT
0
>>> state.RETRACTED
2
>>> state.FOO
Traceback (most recent call last):
   File "<stdin>", line 1, in <module>
AttributeError: 'Enum' object has no attribute 'FOO'
>>> state.tuples()
((0, 'draft'), (1, 'published'), (2, 'retracted'))

එබැවින් මෙය ඔබට රාජ්‍යය වැනි පූර්ණ සංඛ්‍යා නියතයන් ලබා දෙයි. ප්‍රකාශිත සහ ජැංගෝ මාදිලිවල තේරීම් ලෙස භාවිතා කිරීමට ද්වි-ටුපල්.


17

ඩේවිඩ් භාවිතා කිරීම නිර්දේශ කරයි. මම තවත් පියවරක් ඉදිරියට ගොස් කට්ටල භාවිතා කරමි:

months = set('January', 'February', ..., 'December')

දැන් ඔබට කට්ටලයේ ඇති එක් අගයකට අගයක් ගැලපේදැයි පරීක්ෂා කළ හැකිය:

if m in months:

ඩීඑෆ් වැනි, නමුත් මම සාමාන්‍යයෙන් එනූම් වෙනුවට නූල් නියත භාවිතා කරමි.


ඔව් !, ඔබට උරුම කට්ටලයක් ලබා දී getattr ක්‍රමය ලබා දෙන්නේ නම් වඩා හොඳය !
ෂාජපන්

17

එය සරලව තබා ගන්න:

class Enum(object): 
    def __init__(self, tupleList):
            self.tupleList = tupleList

    def __getattr__(self, name):
            return self.tupleList.index(name)

ඉන්පසු:

DIRECTION = Enum(('UP', 'DOWN', 'LEFT', 'RIGHT'))
DIRECTION.DOWN
1

16

මා දුටු හොඳම දේ මෙයයි: "පයිතන්හි පළමු පන්තියේ එනූම්ස්"

http://code.activestate.com/recipes/413486/

එය ඔබට පන්තියක් ලබා දෙන අතර පන්තියේ සියලුම එනූම් අඩංගු වේ. එනමල් එකිනෙක හා සැසඳිය හැකි නමුත් විශේෂිත වටිනාකමක් නැත; ඔබට ඒවා පූර්ණ සංඛ්‍යාවක් ලෙස භාවිතා කළ නොහැක. . .) සෑම enum එකක්ම අද්විතීය අගයකි. ඔබට එනූම්ස් මුද්‍රණය කළ හැකිය, ඔබට ඒවා නැවත කියවිය හැකිය, එනුම් අගය “එනුම්” තුළ ඇති බව ඔබට පරීක්ෂා කළ හැකිය. එය සම්පුර්ණ හා සිනිඳුයි.

සංස්කරණය කරන්න (cfi): ඉහත සබැඳිය පයිතන් 3 අනුකූල නොවේ. මෙන්න මගේ පයිතන් 3 සිට enum.py වරාය:

def cmp(a,b):
   if a < b: return -1
   if b < a: return 1
   return 0


def Enum(*names):
   ##assert names, "Empty enums are not supported" # <- Don't like empty enums? Uncomment!

   class EnumClass(object):
      __slots__ = names
      def __iter__(self):        return iter(constants)
      def __len__(self):         return len(constants)
      def __getitem__(self, i):  return constants[i]
      def __repr__(self):        return 'Enum' + str(names)
      def __str__(self):         return 'enum ' + str(constants)

   class EnumValue(object):
      __slots__ = ('__value')
      def __init__(self, value): self.__value = value
      Value = property(lambda self: self.__value)
      EnumType = property(lambda self: EnumType)
      def __hash__(self):        return hash(self.__value)
      def __cmp__(self, other):
         # C fans might want to remove the following assertion
         # to make all enums comparable by ordinal value {;))
         assert self.EnumType is other.EnumType, "Only values from the same enum are comparable"
         return cmp(self.__value, other.__value)
      def __lt__(self, other):   return self.__cmp__(other) < 0
      def __eq__(self, other):   return self.__cmp__(other) == 0
      def __invert__(self):      return constants[maximum - self.__value]
      def __nonzero__(self):     return bool(self.__value)
      def __repr__(self):        return str(names[self.__value])

   maximum = len(names) - 1
   constants = [None] * len(names)
   for i, each in enumerate(names):
      val = EnumValue(i)
      setattr(EnumClass, each, val)
      constants[i] = val
   constants = tuple(constants)
   EnumType = EnumClass()
   return EnumType


if __name__ == '__main__':
   print( '\n*** Enum Demo ***')
   print( '--- Days of week ---')
   Days = Enum('Mo', 'Tu', 'We', 'Th', 'Fr', 'Sa', 'Su')
   print( Days)
   print( Days.Mo)
   print( Days.Fr)
   print( Days.Mo < Days.Fr)
   print( list(Days))
   for each in Days:
      print( 'Day:', each)
   print( '--- Yes/No ---')
   Confirmation = Enum('No', 'Yes')
   answer = Confirmation.No
   print( 'Your answer is not', ~answer)

මෙම වට්ටෝරුව PEP සඳහා පදනම ලෙස භාවිතා කරන ලද අතර එය ප්රතික්ෂේප කරන ලදී. python.org/dev/peps/pep-0354 මා කැමති එක් දිගුවක්: enum අගයන්ට සාමාජික විචල්‍යයක් තිබිය යුතු අතර එය අභ්‍යන්තර පූර්ණ අගය ලබා ගැනීමට ඔබට ඉඩ සලසයි. වැරදීමකින් පූර්ණ සංඛ්‍යාවක් වෙත එනැම් එකක් දැමිය නොහැකි විය යුතුය, එබැවින් .__int__()ක්‍රමය මඟින් එනූම් සඳහා ව්‍යතිරේකයක් මතු කළ යුතුය; නමුත් වටිනාකම ලබා ගැනීමට ක්‍රමයක් තිබිය යුතුය. පංති අර්ථ දැක්වීමේ වේලාවේදී නිශ්චිත නිඛිල අගයන් සැකසීමට හැකි විය යුතුය, එවිට ඔබට statමොඩියුලයේ නියතයන් වැනි දේ සඳහා එනූම් එකක් භාවිතා කළ හැකිය .
steveha

14

ද්විමය ගොනු ආකෘතියක් විකේතනය කිරීමේ අරමුණින් මට එනුම් පන්තියක් අවශ්‍ය විය. මට අවශ්‍ය වූ අංගයන් වන්නේ සංක්ෂිප්ත එනුම් අර්ථ දැක්වීම, පූර්ණ සංඛ්‍යා හෝ නූල් මගින් reprඑනූම් නිදසුන් නිදහසේ නිර්මාණය කිරීමේ හැකියාව සහ ප්‍රයෝජනවත් සාරාංශයකි. මෙන්න මම අවසන් කළ දේ:

>>> class Enum(int):
...     def __new__(cls, value):
...         if isinstance(value, str):
...             return getattr(cls, value)
...         elif isinstance(value, int):
...             return cls.__index[value]
...     def __str__(self): return self.__name
...     def __repr__(self): return "%s.%s" % (type(self).__name__, self.__name)
...     class __metaclass__(type):
...         def __new__(mcls, name, bases, attrs):
...             attrs['__slots__'] = ['_Enum__name']
...             cls = type.__new__(mcls, name, bases, attrs)
...             cls._Enum__index = _index = {}
...             for base in reversed(bases):
...                 if hasattr(base, '_Enum__index'):
...                     _index.update(base._Enum__index)
...             # create all of the instances of the new class
...             for attr in attrs.keys():
...                 value = attrs[attr]
...                 if isinstance(value, int):
...                     evalue = int.__new__(cls, value)
...                     evalue._Enum__name = attr
...                     _index[value] = evalue
...                     setattr(cls, attr, evalue)
...             return cls
... 

එය භාවිතා කිරීමේ විකාර උදාහරණය:

>>> class Citrus(Enum):
...     Lemon = 1
...     Lime = 2
... 
>>> Citrus.Lemon
Citrus.Lemon
>>> 
>>> Citrus(1)
Citrus.Lemon
>>> Citrus(5)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "<stdin>", line 6, in __new__
KeyError: 5
>>> class Fruit(Citrus):
...     Apple = 3
...     Banana = 4
... 
>>> Fruit.Apple
Fruit.Apple
>>> Fruit.Lemon
Citrus.Lemon
>>> Fruit(1)
Citrus.Lemon
>>> Fruit(3)
Fruit.Apple
>>> "%d %s %r" % ((Fruit.Apple,)*3)
'3 Apple Fruit.Apple'
>>> Fruit(1) is Citrus.Lemon
True

මූලික ලක්ෂණ:

  • str(), int()සහ repr()සියල්ලම හැකි තරම් ප්‍රයෝජනවත් ප්‍රතිදානය නිපදවයි, පිළිවෙලින් ගණන් කිරීමේ නම, එහි පූර්ණ අගය සහ පයිතන් ප්‍රකාශනය ගණනය කිරීම සඳහා නැවත ඇගයීමට ලක් කරයි.
  • ඉදිකිරීම්කරු විසින් ආපසු ලබා දෙන ලද ගණන් කළ අගයන් පූර්ව නිශ්චිත අගයන්ට පමණක් සීමා වේ, අහම්බෙන් එනම් අගයන් නොමැත.
  • ගණනය කළ අගයන් තනි බොත්තම් ය; ඒවා තදින් සැසඳිය හැකියis

එනූම්ස් නිර්වචනය කිරීම පහසු කිරීම සඳහා, තමන්ගේම මෙටැක්ලාස් සහිත සුපිරි පන්තියක් භාවිතා කිරීමට මම ඇත්තෙන්ම කැමතියි. මෙහි නැති වී ඇත්තේ __ අන්තර්ගත__ ක්‍රමයකි. දී ඇති විචල්‍යයක් එනුම් වල කොටසක් දැයි පරීක්ෂා කර බැලීමට මා කැමතිය - බොහෝ දුරට මට අවශ්‍ය වන්නේ ශ්‍රිත පරාමිතියක ඉඩදිය හැකි අගයන් සඳහා එනූම් අවශ්‍ය වන බැවිනි.
xorsyst

මෙය සැබවින්ම මා මුලින් නිර්මාණය කළ අනුවාදයේ තරමක් කැපූ අනුවාදයකි (ඔබට මෙහි සොයාගත හැකිය: enum_strict.py ) v __instancecheck__ක්‍රමයක් නිර්වචනය කරයි . පංති යනු අවස්ථා එකතුවක් නොවේ, එබැවින් 1 in Fruitවිකාරයකි. කෙසේ වෙතත්, සම්බන්ධිත අනුවාදය isinstance(1, Fruit)පංති සහ සිද්ධීන් පිළිබඳ සංකල්පය අනුව වඩාත් නිවැරදි වනු ඇත.
SingleNegationElimination

නමුත් පංති අමතක කිරීම සහ එනූම්ස් අනුව සිතීම, එවිට ඒවා එකතුවක් ලෙස සිතීම අර්ථවත් කරයි. උදාහරණයක් ලෙස, මට ගොනු විවෘත කිරීමේ ක්‍රම රාශියක් ඇත (MODE.OPEN, MODE.WRITE, ආදිය). මගේ ශ්‍රිතයට පරාමිතීන් සත්‍යාපනය කිරීමට මට අවශ්‍යය: MODE හි ප්‍රකාරය නම්: isintance (ප්‍රකාරය, ප්‍රකාරය)
xorsyst


14

පයිතන් හි නව ප්‍රමිතිය PEP 435 වේ , එබැවින් අනාගත පයිතන් අනුවාද වල එනූම් පන්තියක් ලබා ගත හැකිය:

>>> from enum import Enum

කෙසේ වෙතත් දැන් එය භාවිතා කිරීම ආරම්භ කිරීම සඳහා ඔබට PEP සඳහා පෙළඹවූ මුල් පුස්තකාලය ස්ථාපනය කළ හැකිය :

$ pip install flufl.enum

එවිට ඔබට එහි මාර්ගගත මාර්ගෝපදේශය අනුව එය භාවිතා කළ හැකිය :

>>> from flufl.enum import Enum
>>> class Colors(Enum):
...     red = 1
...     green = 2
...     blue = 3
>>> for color in Colors: print color
Colors.red
Colors.green
Colors.blue

10

මම ඇත්තටම ඇලෙක් තෝමස්ගේ විසඳුමට කැමතියි (http://stackoverflow.com/a/1695250):

def enum(**enums):
    '''simple constant "enums"'''
    return type('Enum', (object,), enums)

එය අලංකාර සහ පිරිසිදු පෙනුමකි, නමුත් එය නිශ්චිත ගුණාංග සහිත පන්තියක් නිර්මාණය කරන ශ්‍රිතයක් පමණි.

ශ්‍රිතයේ සුළු වෙනස් කිරීමක් සමඟ, අපට එය තව ටිකක් 'සතුරන්' ලෙස ක්‍රියා කිරීමට ලබා ගත හැකිය:

සටහන: පිග්ට්ක්ගේ නව විලාසිතාවේ 'එනූම්ස්' (Gtk.MessageType.WARNING වැනි) වල හැසිරීම ප්‍රතිනිෂ්පාදනය කිරීමට උත්සාහ කිරීමෙන් මම පහත උදාහරණ නිර්මාණය කළෙමි.

def enum_base(t, **enums):
    '''enums with a base class'''
    T = type('Enum', (t,), {})
    for key,val in enums.items():
        setattr(T, key, T(val))

    return T

මෙය නිශ්චිත වර්ගයක් මත පදනම්ව එනූමයක් නිර්මාණය කරයි. පෙර ශ්‍රිතය මෙන් ආරෝපණ ප්‍රවේශය ලබා දීමට අමතරව, එය ක්‍රියා කරන්නේ ඔබ වර්ග වලට සාපේක්ෂව එනුම් එකක් බලාපොරොත්තු වන ආකාරයට ය. එය මූලික පන්තියට ද උරුම වේ.

උදාහරණයක් ලෙස, පූර්ණ සංඛ්‍යා enums:

>>> Numbers = enum_base(int, ONE=1, TWO=2, THREE=3)
>>> Numbers.ONE
1
>>> x = Numbers.TWO
>>> 10 + x
12
>>> type(Numbers)
<type 'type'>
>>> type(Numbers.ONE)
<class 'Enum'>
>>> isinstance(x, Numbers)
True

මෙම ක්‍රමය සමඟ කළ හැකි තවත් සිත්ගන්නා කරුණක් නම්, ගොඩනංවන ලද ක්‍රම ඉක්මවා යාමෙන් නිශ්චිත හැසිරීම රිසිකරණය කිරීමයි:

def enum_repr(t, **enums):
    '''enums with a base class and repr() output'''
    class Enum(t):
        def __repr__(self):
            return '<enum {0} of type Enum({1})>'.format(self._name, t.__name__)

    for key,val in enums.items():
        i = Enum(val)
        i._name = key
        setattr(Enum, key, i)

    return Enum



>>> Numbers = enum_repr(int, ONE=1, TWO=2, THREE=3)
>>> repr(Numbers.ONE)
'<enum ONE of type Enum(int)>'
>>> str(Numbers.ONE)
'1'

මෙම "මූලික" වර්ගයේ අදහස පිළිවෙළකට ඇත :)
MestreLion

කැපවුණු,, ඔබ ද නව Python 3.4 නිඛිල සමඟ අන්තර් මෙය කළ හැකි බව සලකන්න: python.org/dev/peps/pep-0435/#other-derived-enumerations
bj0

10
def enum(*sequential, **named):
    enums = dict(zip(sequential, [object() for _ in range(len(sequential))]), **named)
    return type('Enum', (), enums)

ඔබ එය නම් කරන්නේ නම්, එය ඔබගේ ගැටලුවයි, නමුත් අගයන් වෙනුවට වස්තු නිර්මාණය නොකිරීම මඟින් ඔබට මෙය කිරීමට ඉඩ දෙයි:

>>> DOG = enum('BARK', 'WALK', 'SIT')
>>> CAT = enum('MEOW', 'WALK', 'SIT')
>>> DOG.WALK == CAT.WALK
False

මෙහි ස්ථානගත කර ඇති වෙනත් ක්‍රියාත්මක කිරීම් භාවිතා කරන විට (මගේ උදාහරණයේ නම් කරන ලද අවස්ථා ද භාවිතා කරන විට) ඔබ කිසි විටෙකත් විවිධ එනූම් වලින් වස්තු සංසන්දනය කිරීමට උත්සාහ නොකරන බවට සහතික විය යුතුය. මක්නිසාද යත් සිදුවිය හැකි අනතුරක් මෙන්න:

>>> DOG = enum('BARK'=1, 'WALK'=2, 'SIT'=3)
>>> CAT = enum('WALK'=1, 'SIT'=2)
>>> pet1_state = DOG.BARK
>>> pet2_state = CAT.WALK
>>> pet1_state == pet2_state
True

අහෝ!


8

PyPI වෙතින් එන enum පැකේජය මගින් enums ශක්තිමත් ලෙස ක්‍රියාත්මක කරයි. කලින් පිළිතුරක සඳහන් වූයේ PEP 354; මෙය ප්‍රතික්ෂේප කළ නමුත් යෝජනාව ක්‍රියාත්මක කරන ලද්දේ http://pypi.python.org/pypi/enum .

භාවිතය පහසු සහ අලංකාරයි:

>>> from enum import Enum
>>> Colors = Enum('red', 'blue', 'green')
>>> shirt_color = Colors.green
>>> shirt_color = Colors[2]
>>> shirt_color > Colors.red
True
>>> shirt_color.index
2
>>> str(shirt_color)
'green'

5

එනුම් සඳහා පන්ති නියතයන් භාවිතා කිරීම පිළිබඳ ඇලෙක්සැන්ඩ්‍රූගේ යෝජනාව හොඳින් ක්‍රියාත්මක වේ.

මිනිස් කියවිය හැකි නූල් නිරූපණයක් සොයා බැලීම සඳහා එක් එක් නියතයන් සඳහා ශබ්ද කෝෂයක් එක් කිරීමට මම කැමතියි.

මෙය අරමුණු දෙකක් ඉටු කරයි: අ) එය ඔබේ එනූම් ලස්සන ලෙස මුද්‍රණය කිරීමට සරල ක්‍රමයක් සපයන අතර ආ) ශබ්දකෝෂය තාර්කිකව නියතයන් කාණ්ඩගත කරයි, එවිට ඔබට සාමාජිකත්වය පරීක්ෂා කළ හැකිය.

class Animal:    
  TYPE_DOG = 1
  TYPE_CAT = 2

  type2str = {
    TYPE_DOG: "dog",
    TYPE_CAT: "cat"
  }

  def __init__(self, type_):
    assert type_ in self.type2str.keys()
    self._type = type_

  def __repr__(self):
    return "<%s type=%s>" % (
        self.__class__.__name__, self.type2str[self._type].upper())

5

මෙන්න මම වටිනා යැයි පෙනෙන වෙනස් ලක්ෂණ කිහිපයක් සහිත ප්‍රවේශයක්:

  • > සහ <සංසන්දනය enum හි අනුපිළිවෙල මත පදනම්ව මිස ශබ්දකෝෂ අනුපිළිවෙලට ඉඩ දෙයි
  • නම, දේපල හෝ දර්ශකය අනුව අයිතමය ඇමතිය හැකිය: xa, x ['a'] හෝ x [0]
  • [:] හෝ [-1] වැනි පෙති කැපීමේ මෙහෙයුම් සඳහා සහය දක්වයි.

සහ වඩාත්ම වැදගත් දෙය වන්නේ විවිධ වර්ගයේ එනූම් අතර සැසඳීම් වළක්වයි !

Http://code.activestate.com/recipes/413486-first-class-enums-in-python මත පදනම්ව .

මෙම ප්‍රවේශයේ වෙනස් දේ නිරූපණය කිරීම සඳහා බොහෝ ඉගැන්වීම් මෙහි ඇතුළත් කර ඇත.

def enum(*names):
    """
SYNOPSIS
    Well-behaved enumerated type, easier than creating custom classes

DESCRIPTION
    Create a custom type that implements an enumeration.  Similar in concept
    to a C enum but with some additional capabilities and protections.  See
    http://code.activestate.com/recipes/413486-first-class-enums-in-python/.

PARAMETERS
    names       Ordered list of names.  The order in which names are given
                will be the sort order in the enum type.  Duplicate names
                are not allowed.  Unicode names are mapped to ASCII.

RETURNS
    Object of type enum, with the input names and the enumerated values.

EXAMPLES
    >>> letters = enum('a','e','i','o','u','b','c','y','z')
    >>> letters.a < letters.e
    True

    ## index by property
    >>> letters.a
    a

    ## index by position
    >>> letters[0]
    a

    ## index by name, helpful for bridging string inputs to enum
    >>> letters['a']
    a

    ## sorting by order in the enum() create, not character value
    >>> letters.u < letters.b
    True

    ## normal slicing operations available
    >>> letters[-1]
    z

    ## error since there are not 100 items in enum
    >>> letters[99]
    Traceback (most recent call last):
        ...
    IndexError: tuple index out of range

    ## error since name does not exist in enum
    >>> letters['ggg']
    Traceback (most recent call last):
        ...
    ValueError: tuple.index(x): x not in tuple

    ## enums must be named using valid Python identifiers
    >>> numbers = enum(1,2,3,4)
    Traceback (most recent call last):
        ...
    AssertionError: Enum values must be string or unicode

    >>> a = enum('-a','-b')
    Traceback (most recent call last):
        ...
    TypeError: Error when calling the metaclass bases
        __slots__ must be identifiers

    ## create another enum
    >>> tags = enum('a','b','c')
    >>> tags.a
    a
    >>> letters.a
    a

    ## can't compare values from different enums
    >>> letters.a == tags.a
    Traceback (most recent call last):
        ...
    AssertionError: Only values from the same enum are comparable

    >>> letters.a < tags.a
    Traceback (most recent call last):
        ...
    AssertionError: Only values from the same enum are comparable

    ## can't update enum after create
    >>> letters.a = 'x'
    Traceback (most recent call last):
        ...
    AttributeError: 'EnumClass' object attribute 'a' is read-only

    ## can't update enum after create
    >>> del letters.u
    Traceback (most recent call last):
        ...
    AttributeError: 'EnumClass' object attribute 'u' is read-only

    ## can't have non-unique enum values
    >>> x = enum('a','b','c','a')
    Traceback (most recent call last):
        ...
    AssertionError: Enums must not repeat values

    ## can't have zero enum values
    >>> x = enum()
    Traceback (most recent call last):
        ...
    AssertionError: Empty enums are not supported

    ## can't have enum values that look like special function names
    ## since these could collide and lead to non-obvious errors
    >>> x = enum('a','b','c','__cmp__')
    Traceback (most recent call last):
        ...
    AssertionError: Enum values beginning with __ are not supported

LIMITATIONS
    Enum values of unicode type are not preserved, mapped to ASCII instead.

    """
    ## must have at least one enum value
    assert names, 'Empty enums are not supported'
    ## enum values must be strings
    assert len([i for i in names if not isinstance(i, types.StringTypes) and not \
        isinstance(i, unicode)]) == 0, 'Enum values must be string or unicode'
    ## enum values must not collide with special function names
    assert len([i for i in names if i.startswith("__")]) == 0,\
        'Enum values beginning with __ are not supported'
    ## each enum value must be unique from all others
    assert names == uniquify(names), 'Enums must not repeat values'

    class EnumClass(object):
        """ See parent function for explanation """

        __slots__ = names

        def __iter__(self):
            return iter(constants)

        def __len__(self):
            return len(constants)

        def __getitem__(self, i):
            ## this makes xx['name'] possible
            if isinstance(i, types.StringTypes):
                i = names.index(i)
            ## handles the more normal xx[0]
            return constants[i]

        def __repr__(self):
            return 'enum' + str(names)

        def __str__(self):
            return 'enum ' + str(constants)

        def index(self, i):
            return names.index(i)

    class EnumValue(object):
        """ See parent function for explanation """

        __slots__ = ('__value')

        def __init__(self, value):
            self.__value = value

        value = property(lambda self: self.__value)

        enumtype = property(lambda self: enumtype)

        def __hash__(self):
            return hash(self.__value)

        def __cmp__(self, other):
            assert self.enumtype is other.enumtype, 'Only values from the same enum are comparable'
            return cmp(self.value, other.value)

        def __invert__(self):
            return constants[maximum - self.value]

        def __nonzero__(self):
            ## return bool(self.value)
            ## Original code led to bool(x[0])==False, not correct
            return True

        def __repr__(self):
            return str(names[self.value])

    maximum = len(names) - 1
    constants = [None] * len(names)
    for i, each in enumerate(names):
        val = EnumValue(i)
        setattr(EnumClass, each, val)
        constants[i] = val
    constants = tuple(constants)
    enumtype = EnumClass()
    return enumtype

4

මුල් එනූම් යෝජනාව වන පීඊපී 354 මීට වසර ගණනාවකට පෙර ප්‍රතික්ෂේප කළද , එය නැවත ඉහළට එයි. යම් ආකාරයක එනුම් 3.2 ට එකතු කිරීමට අදහස් කළ නමුත් එය නැවත 3.3 දක්වා තල්ලු වී පසුව අමතක විය. දැන් PET 435 Python 3.4 හි ඇතුළත් කිරීමට අදහස් කර ඇත. PEP 435 හි විමර්ශන ක්‍රියාත්මක කිරීම වේ flufl.enum.

2013 අප්රේල් වන විට, 3.4 හි සම්මත පුස්තකාලයට යමක් එකතු කළ යුතු බවට පොදු එකඟතාවයක් ඇති බව පෙනේ that එම "යමක්" කුමක් විය යුතුද යන්න පිළිබඳව මිනිසුන්ට එකඟ විය හැකි තාක් කල්. ඒක අමාරු කොටස. මෙතැනින් සහ මෙතැනින් ආරම්භ වන නූල් සහ 2013 මුල් මාසවල තවත් නූල් දුසිම් භාගයක් බලන්න .

මේ අතර, මෙය පැමිණෙන සෑම අවස්ථාවකම, PyPI, ActiveState යනාදියෙහි නව මෝස්තර සහ ක්‍රියාත්මක කිරීම් රාශියක් දිස් වේ, එබැවින් ඔබ FLUFL නිර්මාණයට අකමැති නම්, PyPI සෙවුමක් උත්සාහ කරන්න .


4

පහත සඳහන් දෑ භාවිතා කරන්න.

TYPE = {'EAN13':   u'EAN-13',
        'CODE39':  u'Code 39',
        'CODE128': u'Code 128',
        'i25':     u'Interleaved 2 of 5',}

>>> TYPE.items()
[('EAN13', u'EAN-13'), ('i25', u'Interleaved 2 of 5'), ('CODE39', u'Code 39'), ('CODE128', u'Code 128')]
>>> TYPE.keys()
['EAN13', 'i25', 'CODE39', 'CODE128']
>>> TYPE.values()
[u'EAN-13', u'Interleaved 2 of 5', u'Code 39', u'Code 128']

මම එය ජැන්ගෝ ආකෘති තේරීම් සඳහා භාවිතා කළ අතර එය ඉතා පයිතොනික් පෙනුමකි. එය සැබවින්ම එනුම් නොවේ, නමුත් එය කාර්යය ඉටු කරයි.



3

මෙම විසඳුම ලැයිස්තුවක් ලෙස අර්ථ දක්වා ඇති ගණනය කිරීම් සඳහා පන්තියක් ලබා ගැනීමේ සරල ක්‍රමයකි (තවත් කරදරකාරී පූර්ණ සංඛ්‍යා පැවරුම් නැත):

enumeration.py:

import new

def create(class_name, names):
    return new.classobj(
        class_name, (object,), dict((y, x) for x, y in enumerate(names))
    )

example.py:

import enumeration

Colors = enumeration.create('Colors', (
    'red',
    'orange',
    'yellow',
    'green',
    'blue',
    'violet',
))

2
මෙය පන්ති නිර්මාණය කිරීම සඳහා පැරණි-කාලීන ක්‍රමයකි. type(class_name, (object,), dict(...))ඒ වෙනුවට සරලව භාවිතා නොකරන්නේ ඇයි ?
ටර්මිනස්
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.