-1

I have the following piece of code that was already written by someone else which implements the "enumerated" type like in C, but the code is failing in __cmp__ function with the error:

assert self.EType is other.EType, 
AttributeError: 'str' object has no attribute 'EType'

Could you please let me have some suggestions how to make the comparison between a str and an EType objects, to fix the error?

def enum(*parameters):
    assert parameters, "Empty enums are not supported"

    class EClass(object):
        """ Internal class """
        __slots__ = parameters

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

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

    class EValue(object):
        """ Internal class """
        __slots__ = '__value'

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

        Value = property(lambda self: self.__value)
        EType = property(lambda self: EType)

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

        def __cmp__(self, other):
            assert self.EType is other.EType, \
                "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)

        def __repr__(self):
            return str(parameters[self.__value])

    maximum = len(parameters) - 1
    print ("maximum %d") % maximum
    constants = [None] * len(parameters)

    for i, each in enumerate(parameters):
        val = EValue(i)
        setattr(EClass, each, val)
        constants[i] = val
    constants = tuple(constants)
    EType = EClass()
    return EType

if __name__ == "__main__":
    call_type = "test1"
    if call_type not in enum('test1', 'test2'):
        print 1
zmo
  • 22,917
  • 4
  • 48
  • 82
  • 3
    Can you fix your indentation? It's hard to evaluate code that is not runnable. See http://sscce.org – Blckknght Jan 29 '14 at 10:54
  • There's a ` in the line `call_type = "test1"` - is that an error from posting here or is it in your actual code? – kaspermoerch Jan 29 '14 at 11:24
  • and, i'm not really aware what is the meaning of "Value = property(lambda self: self.__value)" "EType = property(lambda self: EType)" ...could you please explain what is exactly the mechanism of those ? – user3248290 Jan 29 '14 at 11:25
  • @user3248290 have a look at http://stackoverflow.com/questions/17330160/python-how-does-decorator-property-work – zmo Jan 29 '14 at 11:27
  • sorry, it's an error on posting. I'll modify – user3248290 Jan 29 '14 at 11:28
  • 2
    You should *always* post the *full* traceback of errors. – Bakuriu Jan 29 '14 at 11:33
  • 3
    "how to make the comparison between a str and an EType" Well, how _would_ you compare them? The code pretty clearly states that you should not. How would you compare an int and a string, or a double and a list? – tobias_k Jan 29 '14 at 11:35
  • 2
    and btw, if you want to use enums, switch to python 3.4! http://stackoverflow.com/questions/36932/how-can-i-represent-an-enum-in-python – zmo Jan 29 '14 at 11:38
  • @zmo, you will be surprised in how many places you just can't switch to Python 3.! – volcano Jan 29 '14 at 11:41
  • @tobias_k, indeed is stated clearly that the objects should be both enum, so in this case, it is possbile to cast variable call_type to enum? how can I do this. – user3248290 Jan 29 '14 at 12:58
  • @zmo, for the moment is not possbile to switch to Python 3. I have to fix this error in Python 2.6 – user3248290 Jan 29 '14 at 12:59
  • so actually I would like to check it value of call type is in the enum('test1', 'test2') – user3248290 Jan 29 '14 at 13:01
  • and why don't you just use a tuple of strings, if what you want to do is to check a string against the tuple of strings? – zmo Jan 29 '14 at 13:20

1 Answers1

0

The problem is not with the __cmp__ function but with the way you are using the enum:

call_type = "test1"
if call_type not in enum('test1', 'test2'): ...

The objects in the enum are not strings, but instances of EValue, and the __cmp__ function of EValue is not meant to compare with anything else than another EValue (and it would not make much sense to do so, either).

To work around this, you could either check whether the string is in the string representations of the values of the enum, or add a function to the enum class returning the values (stored in __slots__).

the_enum = enum('test1', 'test2')
print "test1" in map(repr, the_enum)
print "test1" in the_enum.values()

The values() method could look like this:

def values(self):
    return tuple(self.__slots__)
tobias_k
  • 74,298
  • 11
  • 102
  • 155
  • Thanks a lot tobias, your solution is working fine. You've save my day :) – user3248290 Jan 29 '14 at 14:04
  • @RickyA Thanks for pointing this out. And just to anticipate any misunderstandings, "flagging as solved" is done with the "accept"-checkmark to the left, not by actually "flagging" this answer as "other -> solved". ;-) – tobias_k Jan 29 '14 at 15:57