7

I have an enum

class Nationality:
        Poland='PL'
        Germany='DE'
        France='FR'
        ...
        Spain='ES'

I have 2 prototypes of methods:

# I want somethink like in c#        
def convert_country_code_to_country_name(country_code):
        print Enum.Parse(typeof(Nationality),country_code)

#this a second solution ,but it has a lot of ifs

def convert_country_code_to_country_name(country_code):
        if country_code=='DE':
                print Nationality.Germany #btw how to print here 'Germany', instead 'DE'

This is how I want call this method:

convert_country_code_to_country_name('DE') # I want here to  print 'Germany'

How to implement it in python?

2
  • 1
    What have you tried? Please post the Python code you tried. We don't like to write code for you. However, we'll help you solve problems with code you've written. Commented Feb 24, 2011 at 12:45
  • 1
    S.Lott and many other people do not like writing code for you. Some people actually enjoy writing code for other, free of charge. However, the solution you get might not be what you want ... Commented Feb 24, 2011 at 12:47

6 Answers 6

6

The best solution would be to create a dictionary right from the start. Your enum doesn't make sense in Python, its just unnecessarily complex. It looks like you are trying to write Java code, which is quite the opposite of what Python code is supposed to look like.

Sign up to request clarification or add additional context in comments.

4 Comments

But what if I want this nationality enum in many modules. Isi is a good idea to write it in every module? I'm c# programmer, so I know that I don't get python conception in full
@user: You can create the dictionary only once and then import it in other modules - it doesn't make a difference if it is a class or not. In general working in a dynamic language like Python can be very different from Java or C#. It takes some time to get used to it, but in the end it is well worth the effort and makes you an overall better programmer.
You have right, but when I stop using enum, then I lost autocomplete from ide and I don't wanna that.
@user: Unfortunately autocomplete will never work as well in a dynamic language compared to a static language. So I wouldn't try too hard not to break it, since otherwise you might again end up with Java code. It's simply one of the downsides of dynamic languages.
4

Python 3.4 has a new Enum data type (which has been backported), which easily supports your use case:

class Nationality(enum.Enum):
    Poland = 'PL'
    Germany = 'DE'
    France = 'FR'
    Spain = 'ES'

To get the enum member from the name:

--> Nationality['France']
<Nationality.France: 'FR'>

To get the enum member from the value:

--> Nationalatiy('FR')
<Nationality.France: 'FR'>

And once you have the enum member:

--> member = Nationality('FR')
--> member.name
'France'
--> member.value
'FR'

Comments

2
class Nationality:
        Poland='PL'
        Germany='DE'
        France='FR'
        Spain='ES'

nationalityDict = {}
for k, v in Nationality.__dict__.iteritems():
    if not k.startswith('__'):
        nationalityDict[v] = k

And now: nationalityDict['DE'] contains Germany.

2 Comments

nationalityDict = {v: k for k, v in vars(Nationality).items() if k[:2] != '__'}
nationalityDict = dict((v, k) for k, v in vars(Nationality).items() if k[:2] != '__') - for Python 2.6 and older...
2

Would you like to use dict instead?

Nationality = { 
    "PL" : "Poland",
    "DE": "Germany"}

print Nationality["DE"] # prints 'Germany'

1 Comment

No, because I use this enum in others module, and I don't want to duplicate code
1

My approach would be like this one (maybe not perfect, but you get the idea):

class Nationality:
        Poland = 'PL'
        Germany = 'DE'
        France = 'FR'

        def convertToCodeFromName(name):
                return getattr(Nationality, name)

        def convertToNameFromCode(code):
                lookFor = None

                for member in dir(Nationality):
                        if (getattr(Nationality, member) == code):
                                lookFor = member
                                break
                return lookFor

print(Nationality.convertToCodeFromName("Poland"))
print(Nationality.convertToNameFromCode("PL"))

Hope this helps.

Comments

0

How about a pure method for converting to enum? Just stash this in a util lib. Or you could put it on a base Enum class and have target_enum default to self.

Could also tweak this to raise an exception instead of using the default value, but the default worked better for my specific case.

from enum import Enum
def to_enum(v,target_enum,default = None):
    '''
    if v is given enum, return it
    if v is an int, convert to enum via int convert
    if v is str convert to enum via string convert
    '''
    ret = default

    if v is None:
        return ret

    if v in target_enum:
        return v

    try:
        return target_enum(int(v))
    except Exception:
        pass

    try:
        return target_enum[str(v)]
    except Exception:
        pass

    return ret

Here is the unittest class for it.

import unittest
from enum import Enum,unique
class EnumTest(Enum):
    T0 = 0
    T1 = 1

class EnumTest2(Enum):
    T0 = 0
    T1 = 1

class EnumUtilTest(unittest.TestCase):
    def test_to_enum(self):
        '''str, int, and Enum should be convertable '''
        r = Util.to_enum(1,EnumTest)
        self.assertEqual(r,EnumTest.T1)
        r = Util.to_enum('T1',EnumTest)
        self.assertEqual(r,EnumTest.T1)
        r = Util.to_enum(EnumTest.T1,EnumTest)
        self.assertEqual(r,EnumTest.T1)
        r = Util.to_enum('1',EnumTest)
        self.assertEqual(r,EnumTest.T1)

    def test_to_enum_fail(self): 
        '''Return None if convert fails'''       
        self.assertIsNone(Util.to_enum( None,EnumTest ))
        self.assertIsNone(Util.to_enum( 'abd',EnumTest ))
        self.assertIsNone(Util.to_enum( 123,EnumTest ))
        self.assertIsNone(Util.to_enum( EnumTest2.T1,EnumTest ))

    def test_to_enum_default(self):
        '''test default param'''
        r = Util.to_enum(EnumTest2.T1,EnumTest,EnumTest.T0)
        self.assertEqual(r,EnumTest.T0)

if __name__ == '__main__':
    unittest.main()

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.