Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Python 3 Enums: Enum inheriting another Enum doesn't work?

I'm just trying to make an Enum in Python 3 by reference of the official Python docs https://docs.python.org/3.4/library/enum.html and specifically 8.13.13.2 and 8.13.13.4 examples.

My target is having an Enum which I can iterate, compare and also having three separate attributes. But I keep finding this error:

AttributeError: can't set attribute

It seems an error in __init__() constructor.

Code:

I tried firstly with one only class like this:

class Hand(Enum):
    FIVE_OF_KIND = (6,'FIVE_OF_KIND',[5])
    FOUR_OF_KIND = (5,'FOUR_OF_KIND',[4,1])
    FULL_HOUSE = (4,'FULL_HOUSE',[3,2])
    THREE_OF_KIND = (3,'THREE_OF_KIND',[3,1,1])
    DOUBLE_PAIR = (2,'DOUBLE_PAIR',[2,2,1])
    PAIR = (1,'PAIR',[2,1,1,1])
    NOTHING = (0,'NOTHING',[1,1,1,1,1])

    def __init__(self, val, name, struct):
        self.val = val
        self.name = name
        self.struct = struct

    def __ge__(self, other):
        if self.__class__ is other.__class__:
            return self.value >= other.value
        return NotImplemented

    def __gt__(self, other):
        if self.__class__ is other.__class__:
            return self.value > other.value
        return NotImplemented

    def __le__(self, other):
        if self.__class__ is other.__class__:
            return self.value <= other.value
        return NotImplemented

    def __lt__(self, other):
        if self.__class__ is other.__class__:
            return self.value < other.value
        return NotImplemented

and secondly with two classes like this:

class OrderedEnum(Enum):
    def __ge__(self, other):
        if self.__class__ is other.__class__:
            return self.value >= other.value
        return NotImplemented

    def __gt__(self, other):
        if self.__class__ is other.__class__:
            return self.value > other.value
        return NotImplemented

    def __le__(self, other):
        if self.__class__ is other.__class__:
            return self.value <= other.value
        return NotImplemented

    def __lt__(self, other):
        if self.__class__ is other.__class__:
            return self.value < other.value
        return NotImplemented


class Hand(OrderedEnum):
    FIVE_OF_KIND = (6,'FIVE_OF_KIND',[5])
    FOUR_OF_KIND = (5,'FOUR_OF_KIND',[4,1])
    FULL_HOUSE = (4,'FULL_HOUSE',[3,2])
    THREE_OF_KIND = (3,'THREE_OF_KIND',[3,1,1])
    DOUBLE_PAIR = (2,'DOUBLE_PAIR',[2,2,1])
    PAIR = (1,'PAIR',[2,1,1,1])
    NOTHING = (0,'NOTHING',[1,1,1,1,1])

    def __init__(self, val, name, struct):
        self.val = val
        self.name = name
        self.struct = struct
like image 616
madtyn Avatar asked Aug 05 '26 04:08

madtyn


1 Answers

Enum objects already have a name attribute (for example, see 8.13.13.3), and apparently you are not allowed to set it – which makes sense when you think about how an enum should behave. You can achieve what you want like this:

from enum import Enum

class OrderedEnum(Enum):
    # Same as your code.

class Hand(OrderedEnum):

    FIVE_OF_KIND  = (6, [5])
    FOUR_OF_KIND  = (5, [4,1])
    FULL_HOUSE    = (4, [3,2])
    THREE_OF_KIND = (3, [3,1,1])
    DOUBLE_PAIR   = (2, [2,2,1])
    PAIR          = (1, [2,1,1,1])
    NOTHING       = (0, [1,1,1,1,1])

    def __init__(self, val, struct):
        # No need to set self.name. It's already handled.
        self.val = val
        self.struct = struct

for h in Hand:
    print((h.name, h.val, h.struct))
like image 81
FMc Avatar answered Aug 06 '26 21:08

FMc