Nasıl Python bir 'Enum' temsil edebilir?

oy
1k

Ben esas olarak bir C # değilim, ama şu anda Python bir proje üzerinde çalışıyorum.

Nasıl Python bir Enum karşılığını temsil edebilir?

Oluştur 31/08/2008 saat 14:55
kaynak kullanıcı
Diğer dillerde...                            


43 cevaplar

oy
711

PEP 435 önce, Python eşdeğer yoktu ama kendi uygulayabilir.

Ben ise, (I net bazı korkunç karmaşık örnekler gördüm) basit böyle bir şey tutarak ister ...

class Animal:
    DOG = 1
    CAT = 2

x = Animal.DOG

Python 3.4 (In PEP 435 ), Enum temel sınıf yapabilirsiniz. Bu, PEP açıklanan ekstra işlevsellik biraz, alır. Örneğin, numaralandırma değerleri tam sayı farklıdır.

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

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

Değerleri yazmak için istemiyorsanız, aşağıdaki kısayolunu kullanın:

class Animal(Enum):
    DOG, CAT = range(2)
Cevap 31/08/2008 saat 15:06
kaynak kullanıcı

oy
18

Hmmm ... Ben bir enum en yakın şey böyle tanımlanan bir sözlük, olacağını varsayalım:

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

veya

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

Sonra, böyle sabitleri için sembolik ad kullanabilirsiniz:

mymonth = months['January']

Orada dizilerini listesi veya dizilerini bir demet gibi diğer seçenekler, fakat sözlük değere erişmek için "sembolik" (sabit dize) yol sağlar sadece bir tanesidir.

Düzenleme: Ben de Alexandru yanıtını gibi!

Cevap 31/08/2008 saat 15:09
kaynak kullanıcı

oy
43

Python için yerleşik bir eşdeğer yoktur enumve diğer cevaplar (ayrıca ilginizi çekebilir kendi uygulanması için fikirler var üst sürümünün üzerine Python yemek kitabı olarak).

Bununla birlikte, bir durumda enumC çağrısında olacağını, genellikle sona sadece basit dizeleri kullanılarak : yol nesneler / nitelikleri uygulanmaktadır, çünkü (C) Python zaten çok hızlı kısa dizeleri ile çalışmak üzere optimize edilmiştir, orada gitmeyeceklerini yüzden 't gerçekten tamsayılar kullanarak herhangi bir performans yararı. Yazım hataları / geçersiz değerler karşı korunmak için seçilen yerlerde kontrolleri ekleyebilirsiniz.

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

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

(Bir sınıf kullanarak oldukları nokta ise otomatik tamamlama faydasını kaybeder olmasıdır)

Cevap 31/08/2008 saat 17:10
kaynak kullanıcı

oy
180

Sayısal değerler gerekiyorsa, burada hızlı yolu şudur:

dog, cat, rabbit = range(3)

Python 3.x size ayrıca bellek israf sakıncası durumunda aralığının geri kalan tüm değerleri kadar emmek ve güvenemezsiniz, hangi sonunda bir rol aldı yer tutucu ekleyebilirsiniz:

dog, cat, rabbit, horse, *_ = range(100)
Cevap 31/08/2008 saat 19:31
kaynak kullanıcı

oy
75

Java ön JDK 5 kullanılmıştır türgüvenli enum model bir dizi avantaja sahiptir. Alexandru yanıtında, bir sınıf ve sınıf düzeyi yaratmak çok gibi alanlar enum değerlerdir; Ancak enum değerleri sınıfının örnekleri ziyade küçük tam sayılardır. Bu, sen onlar basılmış olarak nasıl kontrol ettikleri fayda varsa keyfi yöntemleri ekleyip isinstance kullanarak iddialarda yapabilirsiniz enum değerler sehven küçük tamsayılar eşit mukayese etmeyin avantajı vardır:

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

Yakın tarihli bir piton-dev üzerinde iplik enum kütüphanelerin bir çift vahşi dahil içinde var dikkat çekti:

Cevap 01/09/2008 saat 15:05
kaynak kullanıcı

oy
14

davidg dicts kullanılmasını önerir. Ben bir adım daha ileri gidip setlerini kullanmayı tercih ediyorum:

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

Artık bir değer böyle sette değerlerden biri maçları olmadığını test edebilirsiniz:

if m in months:

dF gibi olsa da, ben genellikle sadece çeteleler yerine dize sabitleri kullanın.

Cevap 02/09/2008 saat 02:20
kaynak kullanıcı

oy
5

çeteleler sınıf sabitleri kullanarak Alexandru önerisi oldukça iyi çalışıyor.

Ben de bir insan tarafından okunabilir dize temsilini arama için sabitler her set için bir sözlük eklemek ister.

a) sizin enum oldukça-yazdırmak için basit bir yol sağlar ve b) Sözlük mantıksal gruplar sabitleri ile üye sınayabilmeleri: Bu iki amaca hizmet eder.

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())
Cevap 19/09/2008 saat 02:37
kaynak kullanıcı

oy
28
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()

Bu şekilde kullanın:

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

Sadece tek bir sembol istiyor ve değerleri hakkında umursamazsak, bu satırı değiştirin:

__metaclass__ = M_add_class_attribs(enumerate(names))

Bununla:

__metaclass__ = M_add_class_attribs((object(), name) for name in names)
Cevap 20/09/2008 saat 10:49
kaynak kullanıcı

oy
2

Çok komik, ben sadece geçen gün bu ihtiyaç vardı ve ... kullanarak değer bir uygulama bulamadım bu yüzden ben kendi yazdım:

import functools

class EnumValue(object):
    def __init__(self,name,value,type):
        self.__value=value
        self.__name=name
        self.Type=type
    def __str__(self):
        return self.__name
    def __repr__(self):#2.6 only... so change to what ever you need...
        return '{cls}({0!r},{1!r},{2})'.format(self.__name,self.__value,self.Type.__name__,cls=type(self).__name__)

    def __hash__(self):
        return hash(self.__value)
    def __nonzero__(self):
        return bool(self.__value)
    def __cmp__(self,other):
        if isinstance(other,EnumValue):
            return cmp(self.__value,other.__value)
        else:
            return cmp(self.__value,other)#hopefully their the same type... but who cares?
    def __or__(self,other):
        if other is None:
            return self
        elif type(self) is not type(other):
            raise TypeError()
        return EnumValue('{0.Name} | {1.Name}'.format(self,other),self.Value|other.Value,self.Type)
    def __and__(self,other):
        if other is None:
            return self
        elif type(self) is not type(other):
            raise TypeError()
        return EnumValue('{0.Name} & {1.Name}'.format(self,other),self.Value&other.Value,self.Type)
    def __contains__(self,other):
        if self.Value==other.Value:
            return True
        return bool(self&other)
    def __invert__(self):
        enumerables=self.Type.__enumerables__
        return functools.reduce(EnumValue.__or__,(enum for enum in enumerables.itervalues() if enum not in self))

    @property
    def Name(self):
        return self.__name

    @property
    def Value(self):
        return self.__value

class EnumMeta(type):
    @staticmethod
    def __addToReverseLookup(rev,value,newKeys,nextIter,force=True):
        if value in rev:
            forced,items=rev.get(value,(force,()) )
            if forced and force: #value was forced, so just append
                rev[value]=(True,items+newKeys)
            elif not forced:#move it to a new spot
                next=nextIter.next()
                EnumMeta.__addToReverseLookup(rev,next,items,nextIter,False)
                rev[value]=(force,newKeys)
            else: #not forcing this value
                next = nextIter.next()
                EnumMeta.__addToReverseLookup(rev,next,newKeys,nextIter,False)
                rev[value]=(force,newKeys)
        else:#set it and forget it
            rev[value]=(force,newKeys)
        return value

    def __init__(cls,name,bases,atts):
        classVars=vars(cls)
        enums = classVars.get('__enumerables__',None)
        nextIter = getattr(cls,'__nextitr__',itertools.count)()
        reverseLookup={}
        values={}

        if enums is not None:
            #build reverse lookup
            for item in enums:
                if isinstance(item,(tuple,list)):
                    items=list(item)
                    value=items.pop()
                    EnumMeta.__addToReverseLookup(reverseLookup,value,tuple(map(str,items)),nextIter)
                else:
                    value=nextIter.next()
                    value=EnumMeta.__addToReverseLookup(reverseLookup,value,(str(item),),nextIter,False)#add it to the reverse lookup, but don't force it to that value

            #build values and clean up reverse lookup
            for value,fkeys in reverseLookup.iteritems():
                f,keys=fkeys
                for key in keys:
                    enum=EnumValue(key,value,cls)
                    setattr(cls,key,enum)
                    values[key]=enum
                reverseLookup[value]=tuple(val for val in values.itervalues() if val.Value == value)
        setattr(cls,'__reverseLookup__',reverseLookup)
        setattr(cls,'__enumerables__',values)
        setattr(cls,'_Max',max([key for key in reverseLookup] or [0]))
        return super(EnumMeta,cls).__init__(name,bases,atts)

    def __iter__(cls):
        for enum in cls.__enumerables__.itervalues():
            yield enum
    def GetEnumByName(cls,name):
        return cls.__enumerables__.get(name,None)
    def GetEnumByValue(cls,value):
        return cls.__reverseLookup__.get(value,(None,))[0]

class Enum(object):
    __metaclass__=EnumMeta
    __enumerables__=None

class FlagEnum(Enum):
    @staticmethod
    def __nextitr__():
        yield 0
        for val in itertools.count():
            yield 2**val

def enum(name,*args):
    return EnumMeta(name,(Enum,),dict(__enumerables__=args))

Al ya da bırakın, ben bunu yapmak için gerekli yaptım :)

Bunu gibi kullanın:

class Air(FlagEnum):
    __enumerables__=('None','Oxygen','Nitrogen','Hydrogen')

class Mammals(Enum):
    __enumerables__=('Bat','Whale',('Dog','Puppy',1),'Cat')
Bool = enum('Bool','Yes',('No',0))
Cevap 21/10/2008 saat 01:08
kaynak kullanıcı

oy
16

Ben kullandılar?

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))

Nasıl kullanılır:

>>> 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'))

Yani bu Django modellerinde seçenek olarak kullanmak size tamsayı state.PUBLISHED gibi sabitleri ve iki dizilerini verir.

Cevap 02/02/2009 saat 22:39
kaynak kullanıcı

oy
118

Eğer gelen gerektiren ne bağlı olacağı için en iyi çözümdür sahte enum .

Basit enum:

Eğer gerekiyorsa enumitibariyle sadece bir liste isimlerinin farklı tanımlayan öğeleri tarafından çözüm Mark Harrison (yukarıda) büyük:

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

Bir kullanarak rangeda herhangi ayarlamanızı sağlar başlangıç değeri :

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

Ayrıca öğeler ait olduğunu gerektiriyorsa Yukarıdakilere ek olarak, kabın çeşit, daha sonra bir sınıfta onları gömmek:

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

enum öğesini kullanmak için, şimdi kapsayıcı adı ve öğe adını kullanmak gerekir:

stype = Stationery.Pen

Kompleks enum:

Enum veya enum daha karmaşık kullanımların uzun listeleri için bu çözümlerin yeterli olmayacaktır. Sen için Will Ware tarafından reçeteye görünebilir Python Enumeration benzetme yayınlanan Python Cookbook . Bunun Bir online sürümü mevcut burada .

Daha fazla bilgi:

PEP 354: Python Sayımlar Python enum için bir öneri ilginç detaylara sahip ve neden reddedildi.

Cevap 07/10/2009 saat 01:47
kaynak kullanıcı

oy
1

aşağıdakileri kullanın.

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']

Ben o kullanılan Django modeli seçimler ve çok pythonic görünüyor. Gerçekten bir Enum değil, ama iş yapar.

Cevap 19/10/2009 saat 09:21
kaynak kullanıcı

oy
2k

De tarif edildiği gibi Numaralamalar Python 3.4 eklenmiştir PEP 435 . Ayrıca edilmiş 3.3 backported, 3.2, 3.1, 2.7, 2.6, 2.5 ve 2.4 pypi ile.

Daha gelişmiş numaralandırma teknikleri denemek için aenum kütüphanesi (2,7, 3.3+, aynı yazar enum34. Kod, örneğin ihtiyacınız py2 ve PY3 arasındaki mükemmel uyumlu değildir __order__piton 2'de ).

  • Kullanmak için enum34, do$ pip install enum34
  • Kullanmak için aenum, do$ pip install aenum

Yükleme enum(hayır numaralar) tamamen farklı ve uyumsuz bir sürümünü kuracaktır.


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)

Veya eşdeğer olarak:

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

Önceki sürümlerde, gerçekleştirerek çeteleler yollarından biridir:

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

burada şöyle kullanılır:

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

Ayrıca kolayca böyle bir şey ile otomatik numaralandırma destekleyebilir:

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

ve böylece gibi kullanılabilir:

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

adlarına geri değerlerini dönüştürmek için destek bu şekilde eklenebilir:

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)

Bu bu adla bir şey üzerine yazar, ancak üretimdeki sizin çeteleler render için yararlıdır. Ters eşlemesi yoksa eğer KeyError atar. İlk örnek ile:

>>> Numbers.reverse_mapping['three']
'THREE'
Cevap 08/11/2009 saat 02:15
kaynak kullanıcı

oy
2

İkili operatörlerin sol ve sağ çağrışımsallık temsil etmek pyparsing bazı sembolik sabitler ihtiyaç vardı. Böyle sınıf sabitlerini kullandı:

# an internal class, not intended to be seen by client code
class _Constants(object):
    pass


# an enumeration of constants for operator associativity
opAssoc = _Constants()
opAssoc.LEFT = object()
opAssoc.RIGHT = object()

istemci kod, bu sabitleri kullanmak istediğinde Şimdi, kullandıkları tüm enum alabilirsiniz:

import opAssoc from pyparsing

Numaralandırma bunun yerine, onlar küçük bir kavram benim kodunda büyük bir ayak izi kadar yapmayız '==' arasında 'is' ile test edilebilir ve kolayca müşteri koduna ithal edilmektedir, benzersizdir. Onlar herhangi fantezi str () davranışı desteklemeyen, ama şimdiye kadar ki olan YAGNI kategorisinde.

Cevap 17/11/2009 saat 19:54
kaynak kullanıcı

oy
13

Bu benim gördüğüm en iyi biridir: "Python Birinci sınıf Numaralandırmalar"

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

Size bir sınıf verir ve sınıf tüm çeteleler içerir. Çeteleler birbirleri ile karşılaştırıldığında, ancak herhangi bir değeri yoktur; Eğer bir tamsayı değeri olarak bunları kullanamaz. Ben tam değerlerdir C çeteleler, alışkınım çünkü (Ben ilk başta bu direndi. Ama sen bir tamsayı olarak kullanamazsınız eğer, bunu genel bunun bir kazan olduğunu düşünüyorum yanlışlıkla bir tamsayı olarak kullanamazsınız .) Her bir numaralama benzersiz bir değerdir. Sen Çeteleler yazdırabilir, size bir sıralama değeri enum "in" olduğunu test edebilirsiniz, onlara adımlayabilirsiniz. Oldukça tam ve ustaca.

Düzenleme (CFI): Yukarıdaki bağlantı Python 3 uyumlu değildir. İşte Python 3'e enum.py benim limanı:

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)
Cevap 18/11/2009 saat 01:51
kaynak kullanıcı

oy
296

İşte bir uygulamasıdır:

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

İşte kullanım şöyledir:

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

print(Animals.DOG)
Cevap 02/02/2010 saat 06:21
kaynak kullanıcı

oy
1

Aaron Mäenpää tarafından önerilen Java enum gibi uygulanmasını takiben, ben aşağıdaki ile çıktı. fikri jenerik ve ayrıştırılabilir yapmaktı.

class Enum:
    #'''
    #Java like implementation for enums.
    #
    #Usage:
    #class Tool(Enum): name = 'Tool'
    #Tool.DRILL = Tool.register('drill')
    #Tool.HAMMER = Tool.register('hammer')
    #Tool.WRENCH = Tool.register('wrench')
    #'''

    name = 'Enum'    # Enum name
    _reg = dict([])   # Enum registered values

    @classmethod
    def register(cls, value):
        #'''
        #Registers a new value in this enum.
        #
        #@param value: New enum value.
        #
        #@return: New value wrapper instance.
        #'''
        inst = cls(value)
        cls._reg[value] = inst
        return inst

    @classmethod
    def parse(cls, value):
        #'''
        #Parses a value, returning the enum instance.
        #
        #@param value: Enum value.
        #
        #@return: Value corresp instance.        
        #'''
        return cls._reg.get(value)    

    def __init__(self, value):
        #'''
        #Constructor (only for internal use).
        #'''
        self.value = value

    def __str__(self):
        #'''
        #str() overload.
        #'''
        return self.value

    def __repr__(self):
        #'''
        #repr() overload.
        #'''
        return "<" + self.name + ": " + self.value + ">"
Cevap 05/03/2010 saat 19:24
kaynak kullanıcı

oy
5

Dan enum paketi PyPI çeteleler sağlam uygulamasını sağlar. Daha önceki cevabı PEP 354 bahsedildiği; Bu reddedildi ama teklifin hayata geçirildi http://pypi.python.org/pypi/enum .

Kullanımı kolay ve şık:

>>> 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'
Cevap 16/03/2010 saat 21:36
kaynak kullanıcı

oy
2

Neden numaralandırma int olmalıdır? Ne yazık ki, her iyi Python dilini değiştirmeden bu üretmeye inşa bakarak düşünemiyorum, yani ipleri kullanacağız:

class Enumerator(object):
    def __init__(self, name):
        self.name = name

    def __eq__(self, other):
        if self.name == other:
            return True
        return self is other

    def __ne__(self, other):
        if self.name != other:
            return False
        return self is other

    def __repr__(self):
        return 'Enumerator({0})'.format(self.name)

    def __str__(self):
        return self.name

class Enum(object):
    def __init__(self, *enumerators):
        for e in enumerators:
            setattr(self, e, Enumerator(e))
    def __getitem__(self, key):
        return getattr(self, key)

Sonra tekrar belki biz doğal olarak yapılandırma dosyaları veya diğer uzak girdi uğruna, dizeleri karşı test edebilirsiniz bile daha iyi şimdi bu.

Örnek:

class Cow(object):
    State = Enum(
        'standing',
        'walking',
        'eating',
        'mooing',
        'sleeping',
        'dead',
        'dying'
    )
    state = State.standing

In [1]: from enum import Enum

In [2]: c = Cow()

In [3]: c2 = Cow()

In [4]: c.state, c2.state
Out[4]: (Enumerator(standing), Enumerator(standing))

In [5]: c.state == c2.state
Out[5]: True

In [6]: c.State.mooing
Out[6]: Enumerator(mooing)

In [7]: c.State['mooing']
Out[7]: Enumerator(mooing)

In [8]: c.state = Cow.State.dead

In [9]: c.state == c2.state
Out[9]: False

In [10]: c.state == Cow.State.dead
Out[10]: True

In [11]: c.state == 'dead'
Out[11]: True

In [12]: c.state == Cow.State['dead']
Out[11]: True
Cevap 07/05/2010 saat 01:05
kaynak kullanıcı

oy
1
def enum( *names ):

    '''
    Makes enum.
    Usage:
        E = enum( 'YOUR', 'KEYS', 'HERE' )
        print( E.HERE )
    '''

    class Enum():
        pass
    for index, name in enumerate( names ):
        setattr( Enum, name, index )
    return Enum
Cevap 26/05/2010 saat 12:14
kaynak kullanıcı

oy
1

Sevdiğim Java ben Python bunun için gereken adımları, enum:

def enum(clsdef):
    class Enum(object):
        __slots__=tuple([var for var in clsdef.__dict__ if isinstance((getattr(clsdef, var)), tuple) and not var.startswith('__')])

        def __new__(cls, *args, **kwargs):
            if not '_the_instance' in cls.__dict__:
                cls._the_instance = object.__new__(cls, *args, **kwargs)
            return cls._the_instance

        def __init__(self):
            clsdef.values=lambda cls, e=Enum: e.values()
            clsdef.valueOf=lambda cls, n, e=self: e.valueOf(n)
            for ordinal, key in enumerate(self.__class__.__slots__):
                args=getattr(clsdef, key)
                instance=clsdef(*args)
                instance._name=key
                instance._ordinal=ordinal
                setattr(self, key, instance)

        @classmethod
        def values(cls):
            if not hasattr(cls, '_values'):
                cls._values=[getattr(cls, name) for name in cls.__slots__]
            return cls._values

        def valueOf(self, name):
            return getattr(self, name)

        def __repr__(self):
            return ''.join(['<class Enum (', clsdef.__name__, ') at ', str(hex(id(self))), '>'])

    return Enum()

Örnek kullanım:

i=2
@enum
class Test(object):
    A=("a",1)
    B=("b",)
    C=("c",2)
    D=tuple()
    E=("e",3)

    while True:
        try:
            F, G, H, I, J, K, L, M, N, O=[tuple() for _ in range(i)]
            break;
        except ValueError:
            i+=1

    def __init__(self, name="default", aparam=0):
        self.name=name
        self.avalue=aparam

Tüm sınıf değişkenleri sadece yapıcısı gibi, bir demet olarak tanımlanır. Şimdiye kadar, adlandırılmış bağımsız değişkenleri kullanamazsınız.

Cevap 04/06/2010 saat 15:33
kaynak kullanıcı

oy
43

Yani, kabul ediyorum. en Python tür güvenliği zorlamak etmeyelim ama aptal hatalarından kendimi korumak istiyorum. Bu yüzden bu konuda ne düşünüyorsunuz?

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

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

Benim çeteleler tanımlanmasında değer çarpışma beni tutar.

>>> Animal.Cat
2

Başka kullanışlı bir avantaj vardır: gerçekten hızlı ters aramalarını:

def name_of(self, i):
    return self.values[i]
Cevap 03/11/2010 saat 22:02
kaynak kullanıcı

oy
28

Öyle gibi Python Çeteleler tanımlamak tercih:

class Animal:
  class Dog: pass
  class Cat: pass

x = Animal.Dog

(Eğer vidalı olurdu Köpek = 1 ve Kedi = 1 desem mesela) Eğer tamsayılar benzersiz olmasını sağlamak konusunda endişelenmenize gerek yok çünkü tamsayılar kullanmaktan daha böcek geçirmez var.

Bu yazım hataları konusunda endişelenmenize gerek yok çünkü dizeleri kullanmaktan daha hata dayanıklı olduğunu (örneğin x == "catt" sessizce başarısız, ancak x == Animal.Catt bir çalışma zamanı istisnadır).

Cevap 29/11/2010 saat 01:05
kaynak kullanıcı

oy
3

İşte bir varyantı olan Alec Thomas'ın çözümü :

def enum(*args, **kwargs):
    return type('Enum', (), dict((y, x) for x, y in enumerate(args), **kwargs)) 

x = enum('POOH', 'TIGGER', 'EEYORE', 'ROO', 'PIGLET', 'RABBIT', 'OWL')
assert x.POOH == 0
assert x.TIGGER == 1
Cevap 14/06/2011 saat 16:29
kaynak kullanıcı

oy
20

Python bir enum başka, çok basit, uygulama, kullanma namedtuple:

from collections import namedtuple

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

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

Veya alternatif olarak,

# 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())

Bu alt sınıfları yukarıdaki yöntem gibi set, bu izin verir:

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

Ama farklı anahtarlar ve değerler olabileceği için fazla esnekliğe sahiptir. Bu veriyor

MyEnum.FOO < MyEnum.BAR

Eğer sıralı sayı değerleri doldurur sürümünü kullanıyorsanız beklendiği gibi hareket etmek.

Cevap 07/08/2011 saat 04:51
kaynak kullanıcı

oy
3

Bu çözüm bir liste (artık can sıkıcı tamsayı atamaları) olarak tanımlanan sayımı için bir sınıf almanın basit bir yoludur:

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',
))
Cevap 18/09/2011 saat 00:26
kaynak kullanıcı

oy
10

Ben bir ikili dosya biçimini deşifre etmek amacıyla, bir Enum sınıfının ihtiyaç imkânı buldum. İstediğim oldu özellikleri özlü enum tanımı, serbestçe ya tamsayı değeri veya dize ve yararlı bir tarafından enum örneklerini oluşturmak için yeteneğidir representation. İşte ben ile sona budur:

>>> 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
... 

bunu kullanarak tuhaf bir örneği:

>>> 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

Anahtar özellikler:

  • str(), int()Ve repr()tüm en kullanışlı olası çıkış, enumartion sırasıyla adını, bir tamsayı değeri, ve geri sayım sonucunu bir Python ifade üretmek.
  • yapıcısı tarafından döndürülen Numaralandırılmış değerler önceden tanımlanmış değerler, hiçbir yanlışlıkla numaralandırma değerlerine kesinlikle sınırlıdır.
  • Numaralandırılmış değerler singletons vardır; Onlar kesinlikle ile karşılaştırılabiliris
Cevap 22/12/2011 saat 00:16
kaynak kullanıcı

oy
8

Gerçekten Alec Thomas'ın çözüm gibi (http://stackoverflow.com/a/1695250):

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

Bu zarif ve temiz görünümlü, ama belirtilen özelliklere sahip bir sınıf oluşturur sadece bir fonksiyon.

işlevine Küçük bir değişiklikle, biz biraz daha 'enumy' davranmaya alabilirsiniz:

NOT: Ben pygtk en yeni stil 'çeteleler' davranışını çoğaltmak deneyerek aşağıdaki örnekler hazırladık (Gtk.MessageType.WARNING gibi)

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

Bu belirli bir tip kapalı dayalı bir enum oluşturur. önceki işlev gibi nitelik erişim sağlayarak ek olarak, bu tipleri bakımından bir Enum beklediğiniz gibi davranır. Aynı zamanda temel sınıfını devralır.

Örnek olarak, tamsayı Çeteleler:

>>> 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

Bu yöntemle yapılabilir bir başka ilginç şey yerleşik yöntemleri geçersiz kılarak belirli davranışını özelleştirmek geçerli:

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'
Cevap 18/01/2012 saat 04:09
kaynak kullanıcı

oy
54

Bir Enum sınıfı tek astar olabilir.

class Enum(tuple): __getattr__ = tuple.index

(Ileri ve arama, anahtarlar, değerler öğeleri, vb ters) Nasıl kullanılır

>>> 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)]
Cevap 08/02/2012 saat 18:59
kaynak kullanıcı

oy
1

(Benim düşüncede, bir const olan) bir numaralandırma uygulamak için bir metaclass kullanın. İşte kod:

class ConstMeta(type):
    '''
    Metaclass for some class that store constants
    '''
    def __init__(cls, name, bases, dct):
        '''
        init class instance
        '''
        def static_attrs():
            '''
            @rtype: (static_attrs, static_val_set)
            @return: Static attributes in dict format and static value set
            '''
            import types
            attrs = {}
            val_set = set()
            #Maybe more
            filter_names = set(['__doc__', '__init__', '__metaclass__', '__module__', '__main__'])
            for key, value in dct.iteritems():
                if type(value) != types.FunctionType and key not in filter_names:
                    if len(value) != 2:
                        raise NotImplementedError('not support for values that is not 2 elements!')
                    #Check value[0] duplication.
                    if value[0] not in val_set:
                        val_set.add(value[0])
                    else:
                        raise KeyError("%s 's key: %s is duplicated!" % (dict([(key, value)]), value[0]))
                    attrs[key] = value
            return attrs, val_set

        attrs, val_set = static_attrs()
        #Set STATIC_ATTRS to class instance so that can reuse
        setattr(cls, 'STATIC_ATTRS', attrs)
        setattr(cls, 'static_val_set', val_set)
        super(ConstMeta, cls).__init__(name, bases, dct)

    def __getattribute__(cls, name):
        '''
        Rewrite the special function so as to get correct attribute value
        '''
        static_attrs = object.__getattribute__(cls, 'STATIC_ATTRS')
        if name in static_attrs:
            return static_attrs[name][0]
        return object.__getattribute__(cls, name)

    def static_values(cls):
        '''
        Put values in static attribute into a list, use the function to validate value.
        @return: Set of values
        '''
        return cls.static_val_set

    def __getitem__(cls, key):
        '''
        Rewrite to make syntax SomeConstClass[key] works, and return desc string of related static value.
        @return: Desc string of related static value
        '''
        for k, v in cls.STATIC_ATTRS.iteritems():
            if v[0] == key:
                return v[1]
        raise KeyError('Key: %s does not exists in %s !' % (str(key), repr(cls)))


class Const(object):
    '''
    Base class for constant class.

    @usage:

    Definition: (must inherit from Const class!
        >>> class SomeConst(Const):
        >>>   STATUS_NAME_1 = (1, 'desc for the status1')
        >>>   STATUS_NAME_2 = (2, 'desc for the status2')

    Invoke(base upper SomeConst class):
    1) SomeConst.STATUS_NAME_1 returns 1
    2) SomeConst[1] returns 'desc for the status1'
    3) SomeConst.STATIC_ATTRS returns {'STATUS_NAME_1': (1, 'desc for the status1'), 'STATUS_NAME_2': (2, 'desc for the status2')}
    4) SomeConst.static_values() returns set([1, 2])

    Attention:
    SomeCosnt's value 1, 2 can not be duplicated!
    If WrongConst is like this, it will raise KeyError:
    class WrongConst(Const):
        STATUS_NAME_1 = (1, 'desc for the status1')
        STATUS_NAME_2 = (1, 'desc for the status2')
    '''
    __metaclass__ = ConstMeta
##################################################################
#Const Base Class ends
##################################################################


def main():
    class STATUS(Const):
        ERROR = (-3, '??')
        OK = (0, '??')

    print STATUS.ERROR
    print STATUS.static_values()
    print STATUS.STATIC_ATTRS

    #Usage sample:
    user_input = 1
    #Validate input:
    print user_input in STATUS.static_values()
    #Template render like:
    print '<select>'
    for key, value in STATUS.STATIC_ATTRS.items():
        print '<option value="%s">%s</option>' % (value[0], value[1])
    print '</select>'


if __name__ == '__main__':
    main()
Cevap 04/04/2012 saat 01:43
kaynak kullanıcı

oy
2

Için (bir enum Değerin adını almak için desteği ile) bir varyantı Alec Thomas'ın düzgün cevap :

class EnumBase(type):
    def __init__(self, name, base, fields):
        super(EnumBase, self).__init__(name, base, fields)
        self.__mapping = dict((v, k) for k, v in fields.iteritems())
    def __getitem__(self, val):
        return self.__mapping[val]

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

Numbers = enum(ONE=1, TWO=2, THREE='three')
print Numbers.TWO
print Numbers[Numbers.ONE]
print Numbers[2]
print Numbers['three']
Cevap 21/06/2012 saat 21:43
kaynak kullanıcı

oy
1

Ben numaralandırma olarak listeleri veya kümeleri kullanmak ister. Örneğin:

>>> packet_types = ['INIT', 'FINI', 'RECV', 'SEND']
>>> packet_types.index('INIT')
0
>>> packet_types.index('FINI')
1
>>>
Cevap 20/11/2012 saat 11:18
kaynak kullanıcı

oy
2

Genellikle kullanmak çözüm dinamik olarak oluşturulan sınıfının bir örneğini almak için bu basit işlevdir.

def enum(names):
    "Create a simple enumeration having similarities to C."
    return type('enum', (), dict(map(reversed, enumerate(
        names.replace(',', ' ').split())), __slots__=()))()

Bunu kullanarak başvurmak istediğiniz isimleri olan bir dize ile işlevini çağırarak kadar basittir.

grade = enum('A B C D F')
state = enum('awake, sleeping, dead')

(Sadece C dilinde benzeri) istenirse bunu yararlanabilir böylece değerler, sadece tam sayılardır.

>>> grade.A
0
>>> grade.B
1
>>> grade.F == 4
True
>>> state.dead == 2
True
Cevap 31/01/2013 saat 12:27
kaynak kullanıcı

oy
1

Python 2.7 ve find_name ()

İşte belki Pythonic daha temizleyici "reverse_mapping" daha kullanmak bazı yardımcı yöntemleri ile seçilen fikrin kolay okunan bir uygulamasıdır. Python> = 2.7 gerektirir.

Aşağıda bazı yorumlar gidermek için numaralamalar oldukça, kodda yazım hatalarını önlemek için yararlıdır devlet makineleri, hata sınıflandırıcılar vs. için örneğin şunlardır

def Enum(*sequential, **named):
  """Generate a new enum type. Usage example:

  ErrorClass = Enum('STOP','GO')
  print ErrorClass.find_name(ErrorClass.STOP)
    = "STOP"
  print ErrorClass.find_val("STOP")
    = 0
  ErrorClass.FOO     # Raises AttributeError
  """
  enums = { v:k for k,v in enumerate(sequential) } if not named else named

  @classmethod
  def find_name(cls, val):
    result = [ k for k,v in cls.__dict__.iteritems() if v == val ]
    if not len(result):
        raise ValueError("Value %s not found in Enum" % val)
    return result[0]

  @classmethod
  def find_val(cls, n):
    return getattr(cls, n)

  enums['find_val'] = find_val
  enums['find_name'] = find_name
  return type('Enum', (), enums)
Cevap 08/04/2013 saat 17:58
kaynak kullanıcı

oy
3

Orijinal enum önerisi ederken, PEP 354 reddedildiğine yıl önce o kadar geri geliyor. Enum çeşit 3.2 eklenecek düşünülmüştü, ancak unutulmuş sonra 3.3 geri itti ve gördü. Ve şimdi bir var PEP 435 Python 3.4 eklenmek üzere tasarlanmıştır. PEP 435 referans uygulamasıdır flufl.enum.

Nisan 2013 tarihinden itibaren, bu genel bir fikir birliği var gibi görünüyor şey -olarak 3.4 uzun insanlar "bir şey" ne olması gerektiği üzerinde anlaşabileceği olarak standart kütüphaneye eklenmelidir. Bu zor kısmı. Ipler başlayan Bkz burada ve burada 2013 yılının ilk aylarında diğer konuları ve yarım düzine.

Bu arada, bu her geldiklerinde, yeni tasarımlar ve uygulamalar ile ilgili bir takım vb PyPI, ActiveState, görünür, bu yüzden FLUFL tasarımını beğenmezseniz, bir deneyin PyPI arama .

Cevap 19/04/2013 saat 00:16
kaynak kullanıcı

oy
29

2013-05-10 tarihinde Guido kabul etme kararı PEP 435 Python 3.4 standart kütüphaneye. Bu Python nihayet sayımları için yerleşik desteğe sahip olduğu anlamına gelir!

Python 3.3, 3.2, 3.1, 2.7, 2.6, 2.5 ve 2.4 için bir backport bulunmaktadır. Sanki Pypi üzerinde bulunuyor enum34 .

Beyan:

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

Temsil:

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

Tekrar:

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

Programlı erişim:

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

Daha fazla bilgi için, bkz önerisi . Resmi belgeler muhtemelen yakında takip edecektir.

Cevap 10/05/2013 saat 15:09
kaynak kullanıcı

oy
7

Python yeni standart olan PEP 435 , bu nedenle bir Enum sınıfı Python gelecekteki sürümlerinde kullanılabilir olacaktır:

>>> from enum import Enum

Ancak şimdi yükleyebilirsiniz kullanmaya başlamak için orijinal kütüphane PEP motive:

#sudo pip install flufl.enum   //or #sudo easy_install flufl.enum

Sonra , online rehber başına olarak kullanabilirsiniz :

>>> 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
Cevap 10/05/2013 saat 15:22
kaynak kullanıcı

oy
3

İşte değerli buluyorum bazı farklı özelliklere sahip bir yaklaşımdır:

  • verir> ve <karşılaştırma amacıyla enum değil sözcüksel düzene göre
  • ad, mülkiyet veya indeks tarafından öğeyi ele alabilir: xa, x [ 'a'] veya x [0]
  • [:] Gibi dilimleme işlemleri desteklediği veya [-1]

ve en önemlisi farklı türde çeteleler arasında karşılaştırmalar önler !

Yakından göre http://code.activestate.com/recipes/413486-first-class-enums-in-python .

Birçok doctestler bu yaklaşımın nelerin farklı olduğunu göstermek için buraya dahil.

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
Cevap 19/06/2013 saat 20:30
kaynak kullanıcı

oy
2

cevaplar listesinde bu bir görmedik, burada ben çırpılmış biridir. Bu anahtar kelime ve len () yöntemiyle 'in' kullanımına izin verir:

class EnumTypeError(TypeError):
    pass

class Enum(object):
    """
    Minics enum type from different languages
    Usage:
    Letters = Enum(list('abc'))
    a = Letters.a
    print(a in Letters) # True
    print(54 in Letters) # False
    """
    def __init__(self, enums):
        if isinstance(enums, dict):
            self.__dict__.update(enums)
        elif isinstance(enums, list) or isinstance(enums, tuple):
            self.__dict__.update(**dict((v,k) for k,v in enumerate(enums)))
        else:
            raise EnumTypeError

    def __contains__(self, key):
        return key in self.__dict__.values()

    def __len__(self):
        return len(self.__dict__.values())


if __name__ == '__main__':
    print('Using a dictionary to create Enum:')
    Letters = Enum(dict((v,k) for k,v in enumerate(list('abcde'))))
    a = Letters.a
    print('\tIs a in e?', a in Letters)
    print('\tIs 54 in e?', 54 in Letters)
    print('\tLength of Letters enum:', len(Letters))

    print('\nUsing a list to create Enum:')
    Letters = Enum(list('abcde'))
    a = Letters.a
    print('\tIs a in e?', a in Letters)
    print('\tIs 54 in e?', 54 in Letters)
    print('\tLength of Letters enum:', len(Letters))

    try:
        # make sure we raise an exception if we pass an invalid arg
        Failure = Enum('This is a Failure')
        print('Failure')
    except EnumTypeError:
        print('Success!')

Çıktı:

Using a dictionary to create Enum:
        Is a in e? True
        Is 54 in e? False
        Length of Letters enum: 5

Using a list to create Enum:
        Is a in e? True
        Is 54 in e? False
        Length of Letters enum: 5
Success!
Cevap 05/09/2013 saat 03:12
kaynak kullanıcı

oy
14

Python 3.4 itibaren çeteleler için resmi destek olacaktır. Sen dokümantasyon ve örnekler bulabilirsiniz Python 3.4 dokümantasyon sayfasından burada .

Numaralandırma onları kolay okuma yazma yapar sınıf sözdizimi kullanılarak oluşturulur. Alternatif bir oluşturma yöntemi Fonksiyonel API açıklanmaktadır. aşağıdaki gibi bir numaralandırma, alt enum tanımlamak için:

from enum import Enum
class Color(Enum):
     red = 1
     green = 2
     blue = 3
Cevap 11/12/2013 saat 11:49
kaynak kullanıcı

oy
2

İşte burada bulduğu güzel bir Python tarifi: http://code.activestate.com/recipes/577024-yet-another-enum-for-python/

def enum(typename, field_names):
    "Create a new enumeration type"

    if isinstance(field_names, str):
        field_names = field_names.replace(',', ' ').split()
    d = dict((reversed(nv) for nv in enumerate(field_names)), __slots__ = ())
    return type(typename, (object,), d)()

Örnek kullanım:

STATE = enum('STATE', 'GET_QUIZ, GET_VERSE, TEACH')

Daha fazla detay tarifi sayfasından bulunabilir.

Cevap 17/03/2014 saat 15:34
kaynak kullanıcı

oy
10

sade tutun:

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

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

Sonra:

DIRECTION = Enum(('UP', 'DOWN', 'LEFT', 'RIGHT'))
DIRECTION.DOWN
1
Cevap 28/03/2014 saat 19:44
kaynak kullanıcı

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

bunu adı varsa, bir sorun, ancak bunun yerine değerlerin nesneler yaratmak değilse bunu yapmak için izin verir:

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

Burada oturtulmuş diğer uygulamaları kullanırken (bizim örneğimizde adlandırılmış örneklerini kullanırken de), farklı çeteleler gelen nesneleri karşılaştırmak için deneyin asla emin olmalıdır. Burada olası bir tuzak var:

>>> 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

Olmadı!

Cevap 11/11/2014 saat 07:26
kaynak kullanıcı

Cookies help us deliver our services. By using our services, you agree to our use of cookies. Learn more