17

I would like to add a method to my enum.

class Kerneltype(Enum):
    tube = 0
    subspace_KDE = 1
    deltashift = 2
    dist_sens_via_mass_1 = 3

    def aslist(self):
        return [self.tube, self.subspace_KDE, self.deltashift, self.dist_sens_via_mass_1]

    def fromint(self, int):
        return self.aslist()[int]

does not work. Instead of

Kerneltype.aslist()

I currently have to do

[kt[1] for kt in ob.Kerneltype.__members__.items()]
Make42
  • 12,236
  • 24
  • 79
  • 155
  • 9
    "Doesn't work" is a very _vague_ problem description. Please be more specific and provide us with any error messages you're getting. – ForceBru May 23 '17 at 16:19
  • 5
    Note, your `aslist` method does not do anything that `list(Kerneltype)` would not give you automatically. – Daniel Roseman May 23 '17 at 16:23
  • 1
    The docs can be very helpful here; you don't need a method to [iterate over your enum](https://docs.python.org/3/library/enum.html#iteration) and you can access it by integer index by [calling it like a function](https://docs.python.org/3/library/enum.html#programmatic-access-to-enumeration-members-and-their-attributes). – Ben May 23 '17 at 16:31
  • @Ben The function call actually expects a value not index. – Ashwini Chaudhary May 23 '17 at 16:47
  • @AshwiniChaudhary `Kerneltype.fromi(1) is Kerneltype(1)` is a `True` epxpression- just to make sure, I implemented this with those @classmethod decorators from your answer and checked. – Ben May 23 '17 at 18:17
  • 2
    @Ben That's working because the items in the Enum are also similar to indices, change `subspace_KDE` to say 5 and then try again. – Ashwini Chaudhary May 23 '17 at 18:18
  • @AshwiniChaudhary Okay I see what you mean. Thanks for the help! – Ben May 23 '17 at 18:23

4 Answers4

19

You created an instance method, so aslist only exists on instances of Kerneltype (i.e. the enum members themselves). You need a classmethod instead:

@classmethod
def aslist(cls):
    return [cls.tube, cls.subspace_KDE, cls.deltashift, cls.dist_sens_via_mass_1]
>>> Kerneltype.aslist()
[<Kerneltype.tube: 0>, <Kerneltype.subspace_KDE: 1>, <Kerneltype.deltashift: 2>, <Kerneltype.dist_sens_via_mass_1: 3>]
poke
  • 369,085
  • 72
  • 557
  • 602
  • Why @classmethod and not @staticmethod? – uuu777 Mar 22 '21 at 03:34
  • @zzz777 See [this question for the difference](https://stackoverflow.com/q/136097/216074). Static methods don’t have access to the class type, and as such its class properties. – poke Mar 22 '21 at 12:21
  • Sorry could not decipher much from the discussion. I am only using classes because I want to access/manipulate data encapsulated in a class (my past is in c++). The discussion was centered around printing class names in various ways. There are static variables in a class and class variables, is the only big difference is that class variables/methods could be modified by derived classes? It will be really nice if you can shed some light. – uuu777 Mar 22 '21 at 13:57
  • @zzz777 Python doesn’t have “static variables” in the sense of other languages. The members in OP’s example, e.g. `tube` and `deltashift`, are [class variables](https://docs.python.org/3/tutorial/classes.html#class-and-instance-variables) that are stored on the class/type instead of an instance. If you want to access those, you will need to have a reference to the type. That reference is the `cls` that is passed to `@classmethod` methods but not `@staticmethod` methods. – poke Mar 22 '21 at 15:11
  • Sorry it seems like some sort of misunderstanding I am using static variables in classes in python3 right now and it seems working well. Sorry again I will try to formulate my question differently. – uuu777 Mar 22 '21 at 16:02
6

You should be defining your methods with the classmethod decorator as you are calling them from the class and not the Enum member.

@classmethod
def aslist(cls):
    return [cls.tube, cls.subspace_KDE, cls.deltashift, cls.dist_sens_via_mass_1]

@classmethod
def fromint(cls, int):
    return cls.aslist()[int]

As others have mentioned in comments, your aslist() method is not required and you can directly use list() on it and it by default preserves the order of definition. Only difference is that it doesn't return the aliases.

>>> list(Kerneltype)
[<Kerneltype.tube: 0>, <Kerneltype.subspace_KDE: 1>, <Kerneltype.deltashift: 2>, <Kerneltype.dist_sens_via_mass_1: 3>]
Ethan Furman
  • 63,992
  • 20
  • 159
  • 237
Ashwini Chaudhary
  • 244,495
  • 58
  • 464
  • 504
1

You missed the classmethod decorator:

@classmethod
def aslist(self):
    return [self.tube, self.subspace_KDE, self.deltashift, self.dist_sens_via_mass_1]
Sнаđошƒаӽ
  • 16,753
  • 12
  • 73
  • 90
0

The issue with what you do is trying to access enum values via self whereas you should access them as you would normally via the enum.

from enum import Enum

class V(Enum):
    V1 = (1, 2)
    V2 = (2, 3)
    def getKey(v: float):
        return [k for k in list(V) if v > k.value[0] and v < k.value[1]]

V.getKey(1.1) #  [<V.V1: (1, 2)>]
V.getKey(1.1)[0].value # (1, 2) 
Sp3c7r00M
  • 79
  • 8