rubikonx9
rubikonx9

Reputation: 1413

Using __class__ to get properties when deriving Enum

I want to extend Enum class and add a utility function, which would be utilized by other classes.

Consider this code:

from enum import Enum

class BaseEnum(Enum):
    def get_items():
        print(__class__)
        return __class__.__members__.items()

class DerivedEnum(BaseEnum):
    X = 1
    Y = 2

print(BaseEnum.get_items())
print(DerivedEnum.get_items())

This, obviously, does not work as intended, as __class__ always refers to BaseEnum.

I know I can change the code to:

from enum import Enum

def get_enum_items(enum_class):
    return enum_class.__members__.items()

class AnotherEnum(Enum):
    X = 1
    Y = 2

    def get_items():
        return get_enum_items(__class__)

print(AnotherEnum.get_items())

This indeed does what I wanted, but requires me to write exactly the same method for all my Enum sub-classes I write.

Is there anything like __actual_class__ in Python? I guess it'd be needed to make something like a virtual static method.

As far as I understand Enum class, we're never actually instantiating it, so I can see no way to use references to instances (such as type(self)).

Upvotes: 1

Views: 51

Answers (2)

Ethan Furman
Ethan Furman

Reputation: 69120

Using a classmethod is the most straight-forward way, as shown by bruno's answer. However, unless you need the result as a list of (name, member) tuples then the easiest way is:

>>> list(DerivedEnum)
[<DerivedEnum.X: 1>, <DerivedEnum.Y: 2>]

As far as instantiating Enum classes: each member is an instance of its class, so you could do:

def get_items(self):
    return self.__class__.__members__.items()

While the classmethod is a better fit in this case (since you are accessing only class data), it is possible to add behavior that depends on the member, just like with normal classes/instances.

Upvotes: 1

bruno desthuilliers
bruno desthuilliers

Reputation: 77912

Seems to work with a classmethod:

from enum import Enum

class BaseEnum(Enum):
    @classmethod
    def get_items(cls):
        print(cls)
        return cls.__members__.items()

class DerivedEnum(BaseEnum):
    X = 1
    Y = 2

print(BaseEnum.get_items())
print(DerivedEnum.get_items())

Upvotes: 2

Related Questions