Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to correctly define a classmethod that accesses a value of a mangled child attribute?

In Python, how do I correctly define a classmethod of a parent class that references an attribute of a child class?

from enum import Enum


class LabelledEnum(Enum):
    @classmethod
    def list_labels(cls):
        return list(l for c, l in cls.__labels.items())


class Test(LabelledEnum):
    A = 1
    B = 2
    C = 3

    __labels = {
        1: "Label A",
        2: "Custom B",
        3: "Custom label for value C + another string",
    }


print(Test.list_labels())
# expected output
# ["Label A", "Custom B", "Custom label for value C + another string"]

In the code above I expect that Test.list_labels() will correctly print out the labels, however because the __labels dictionary is defined with the double underscore, I cannot access it correctly.

The reason I wanted to have double underscore is to make sure that the labels would not show up when iterating over the enumerator, e.g. list(Test) should not show the dictionary containing labels.

like image 668
SultanOrazbayev Avatar asked Sep 03 '25 17:09

SultanOrazbayev


1 Answers

While the getattr method works, a more elegant solution is to make LabelledEnum a mix-in instead, and define the label with the value:

from enum import Enum

class LabelledEnumMixin:

    labels = {}

    def __new__(cls, value, label):
        member = object.__new__(cls)
        member._value_ = value
        member.label = label
        cls.labels[value] = label
        return member

    @classmethod
    def list_labels(cls):
        return list(l for c, l in cls.labels.items())


class Test(LabelledEnumMixin, Enum):
    A = 1, "Label A"
    B = 2, "Custom B"
    C = 3, "Custom label for value C + another string"

Disclosure: I am the author of the Python stdlib Enum, the enum34 backport, and the Advanced Enumeration (aenum) library.

like image 174
Ethan Furman Avatar answered Sep 05 '25 06:09

Ethan Furman