Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How do define an attribute in Python 3 enum class that is NOT an enum value? [duplicate]

How to define an attribute in a Python 3 enum class that is NOT an enum value?

class Color(Enum):
    red = 0
    blue = 1
    violet = 2
    foo = 'this is a regular attribute'
    bar = 55  # this is also a regular attribute

But this seems to fail for me. It seems that Color tries to include foo and bar as part of its enum values.

EDIT: Lest you think I'm not using Enum in a way that's intended... For example, take the official Python documentation's example enum class Planet (docs.python.org/3/library/enum.html#planet). Note that they define the gravitational constant G within the surface_gravity() method. But this is weird code. A normal programmer would say, set that constant G once, outside the function. But if I try to move G out (but not to global scope, just class scope), then I run into the issue I'm asking about here.

like image 689
eng Avatar asked Oct 08 '15 06:10

eng


People also ask

Can enums have attributes?

An enum can, just like a class , have attributes and methods. The only difference is that enum constants are public , static and final (unchangeable - cannot be overridden).

Can enums have the same value Python?

By definition, the enumeration member values are unique. However, you can create different member names with the same values. In this example, the Color enumeration has the RED , CRIMSON , and SALMON members with the same value 1.

What does enum Auto () do?

With the help of enum. auto() method, we can get the assigned integer value automatically by just using enum. auto() method. Automatically assign the integer value to the values of enum class attributes.

How do you define an enum variable?

An enum type is a special data type that enables for a variable to be a set of predefined constants. The variable must be equal to one of the values that have been predefined for it. Common examples include compass directions (values of NORTH, SOUTH, EAST, and WEST) and the days of the week.


2 Answers

The point of the Enum type is to define enum values, so non-enum values are theoretically out of scope for this type. For constants, you should consider moving them out of the type anyway: They are likely not directly related to the enum values (but rather some logic that builds on those), and also should be a mutable property of the type. Usually, you would just create a constant at module level.

If you really need something on the type, then you could add it as a class method:

class Color(Enum):
    red = 0
    blue = 1
    violet = 2
    bar = 55

    @classmethod
    def foo (cls):
        return 'this is a not really an attribute…'

And using the classproperty descriptor from this answer, you can also turn this into a property at class level which you can access as if it was a normal attribute:

class Color(enum.Enum):
    red = 0
    blue = 1
    violet = 2
    bar = 55

    @classproperty
    def foo (cls):
        return 'this is a almost a real attribute'
>>> Color.foo
'this is a almost a real attribute'
>>> list(Color)
[<Color.red: 0>, <Color.blue: 1>, <Color.violet: 2>, <Color.bar: 55>]
like image 192
poke Avatar answered Oct 11 '22 21:10

poke


When building an enum.Enum class, all regular attributes become members of the enumeration. A different type of value does not make a difference.

By regular attributes I mean all objects that are not descriptors (like functions are) and excluded names (using single underscore names, see the Allowed members and attributes of enumerations section).

If you need additional attributes on the final enum.Enum object, add attributes afterwards:

class Color(Enum):
    red = 0
    blue = 1
    violet = 2

Color.foo = 'this is a regular attribute'
Color.bar = 55

Demo:

>>> from enum import Enum
>>> class Color(Enum):
...     red = 0
...     blue = 1
...     violet = 2
... 
>>> Color.foo = 'this is a regular attribute'
>>> Color.bar = 55
>>> Color.foo
'this is a regular attribute'
>>> Color.bar
55
>>> Color.red
<Color.red: 0>
>>> list(Color)
[<Color.red: 0>, <Color.blue: 1>, <Color.violet: 2>]
like image 27
Martijn Pieters Avatar answered Oct 11 '22 19:10

Martijn Pieters