Python'da int Enum dönüştürmek nasıl?


96

Python 2.7.6 ile yeni Enum özelliğini ( backport enum34 aracılığıyla ) kullanma.

Aşağıdaki tanım göz önüne alındığında, bir int'i karşılık gelen Enum değerine nasıl dönüştürebilirim?

from enum import Enum

class Fruit(Enum):
    Apple = 4
    Orange = 5
    Pear = 6

Dönüştürmeyi yapmak için bir dizi if ifadesi oluşturabileceğimi biliyorum, ancak dönüştürmenin kolay bir yolu var mı? Temel olarak, bir enum değeri döndüren bir ConvertIntToFruit (int) işlevi istiyorum.

Benim kullanım durumum, her kaydı bir nesneye okuduğum bir kayıt csv dosyam olması. Dosya alanlarından biri, bir numaralandırmayı temsil eden bir tamsayı alanıdır. Nesneyi doldururken, bu tamsayı alanını dosyadan nesnedeki karşılık gelen Enum değerine dönüştürmek istiyorum.

Yanıtlar:


165

EnumSınıfı 'arayın' :

Fruit(5)

dönüşe 5içine Fruit.Orange:

>>> from enum import Enum
>>> class Fruit(Enum):
...     Apple = 4
...     Orange = 5
...     Pear = 6
... 
>>> Fruit(5)
<Fruit.Orange: 5>

Gönderen numaralandırma üyeleri ve nitelikleri programlı erişim belgelerin bölümünde:

Bazen numaralandırmalardaki üyelere programlı olarak erişmek yararlıdır (yani Color.red, program yazma zamanında tam renk bilinmediği için yapılamayacak durumlar). Enumbu tür erişime izin verir:

>>> Color(1)
<Color.red: 1>
>>> Color(3)
<Color.blue: 3>

İlgili bir notta: bir enum üyesinin adını içeren bir dize değerini eşlemek için aboneliği kullanın:

>>> s = 'Apple'
>>> Fruit[s]
<Fruit.Apple: 4>

Teşekkürler, belgeleri yeniden okurken bunu aldım. İlk göz atmamda bana net gelmedi. Ayrıca bir dize kullanmayı denedim ve numaralandırma değeri de bir dize olduğunda çalıştığını görmek güzel ve herhangi bir rastgele nesne değeri varsayıyorum.
Kullanıcı

Çok iyi, bu yüzden dönüşüm değere göredir. Enum listesini filtrelemek ve isim özniteliklerine göre eşleşmeyi almak için bir liste anlama dışında isme göre bir analog var mı?
jxramos

4
@jxramos cevabımdaki dokümantasyon bağlantısını takip ediyor, orada açıkça kapsanmıştır. Madde erişimini kullanın: Fruit['Orange'].
Martijn Pieters

Bingo, çok harika! Ben için sayfa aradı convert, coerceve castbaşka bir şey isabet etmedi. Görünüşe göre sihir öyleydi access enum members by name, use item access. Perfecto, çok teşekkürler, kodumu bu sözdizimi ile temizleyeceğim.
jxramos

Daha da iyisi, "foobar" in Fruit.__members__üyelik için test etmek gibi şeyleri kullanabilir ve hatta Fruit.get( 'foobar', Fruit.Orange )varsayılan Enum lezzetini elde etmek için çekebilirim . Kodum, daha önce ortaya koyduğum tüm bu aksesuar arama iskelesini kaldırarak çok daha basitleştirilmiş görünüyor.
jxramos

1

Ben basit bir deyişle olduğunu dönüştürmek olduğunu düşünüyorum intiçine değeri Enumarayarak EnumType(int_value)bu erişime sonra, namebir Enumnesne:

my_fruit_from_int = Fruit(5) #convert to int
fruit_name = my_fruit_from_int.name #get the name
print(fruit_name) #Orange will be printed here

Veya bir işlev olarak:

def convert_int_to_fruit(int_value):
    try:
        my_fruit_from_int = Fruit(int_value)
        return my_fruit_from_int.name
    except:
        return None

-1

Benzer bir şey istedim, böylece değer çiftinin herhangi bir kısmına tek bir referanstan erişebilecektim. Vanilya versiyonu:

#!/usr/bin/env python3


from enum import IntEnum


class EnumDemo(IntEnum):
    ENUM_ZERO       = 0
    ENUM_ONE        = 1
    ENUM_TWO        = 2
    ENUM_THREE      = 3
    ENUM_INVALID    = 4


#endclass.


print('Passes')
print('1) %d'%(EnumDemo['ENUM_TWO']))
print('2) %s'%(EnumDemo['ENUM_TWO']))
print('3) %s'%(EnumDemo.ENUM_TWO.name))
print('4) %d'%(EnumDemo.ENUM_TWO))
print()


print('Fails')
print('1) %d'%(EnumDemo.ENUM_TWOa))

Başarısızlık, beklendiği gibi bir istisna atar.

Daha sağlam bir versiyon:

#!/usr/bin/env python3


class EnumDemo():


    enumeration =   (
                        'ENUM_ZERO',    # 0.
                        'ENUM_ONE',     # 1.
                        'ENUM_TWO',     # 2.
                        'ENUM_THREE',   # 3.
                        'ENUM_INVALID'  # 4.
                    )


    def name(self, val):
        try:

            name = self.enumeration[val]
        except IndexError:

            # Always return last tuple.
            name = self.enumeration[len(self.enumeration) - 1]

        return name


    def number(self, val):
        try:

            index = self.enumeration.index(val)
        except (TypeError, ValueError):

            # Always return last tuple.
            index = (len(self.enumeration) - 1)

        return index


#endclass.


print('Passes')
print('1) %d'%(EnumDemo().number('ENUM_TWO')))
print('2) %s'%(EnumDemo().number('ENUM_TWO')))
print('3) %s'%(EnumDemo().name(1)))
print('4) %s'%(EnumDemo().enumeration[1]))
print()
print('Fails')
print('1) %d'%(EnumDemo().number('ENUM_THREEa')))
print('2) %s'%(EnumDemo().number('ENUM_THREEa')))
print('3) %s'%(EnumDemo().name(11)))
print('4) %s'%(EnumDemo().enumeration[-1]))

Doğru kullanılmadığında bu, bir istisna oluşturmayı önler ve bunun yerine bir hata göstergesini geri gönderir. Bunu yapmanın daha Pythonic yolu "Hiçbiri" ni geri almaktır, ancak benim özel uygulamam metni doğrudan kullanır.


Neden bir Enum örneğindeki __int__ve __str__yöntemlerini tanımlamıyorsunuz ?
Tim
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.