I defined the following Enum in Python:
class Unit(Enum):
GRAM = ("g")
KILOGRAM = ("kg", GRAM, 1000.0)
def __init__(self, symbol, base_unit = None, multiplier = 1.0):
self.symbol = symbol
self.multiplier = multiplier
self.base_unit = self if base_unit is None else base_unit
I would expect that
print(Unit.GRAM.base_unit)
print(Unit.KILOGRAM.base_unit)
will return
Unit.GRAM
Unit.GRAM
However, what I get is quite confusing
Unit.GRAM
g
Why is it so?
Enum implicitly and therefore cannot extend another class. This means extensibility for enums most be derived from a different source. This is about as close as you can get to shared state when it comes to enums. As Johan Sjöberg said above, it might just be easiest to simply combine the enums into another enum.
equals method uses == operator internally to check if two enum are equal. This means, You can compare Enum using both == and equals method.
1. Two enum names can have same value. For example, in the following C program both 'Failed' and 'Freezed' have same value 0.
The way Python defines a class involves creating a new scope, processing a bunch of statements (variable assignments, function definitions, etc.), and then actually creating a class object based on the local variables which exist after all those statements have run. Nothing gets converted into Enum
instances until that last step.
You could understand it somewhat like this:
def make_class_Unit():
GRAM = ("g")
KILOGRAM = ("kg", GRAM, 1000.0)
def __init__(self, symbol, base_unit = None, multiplier = 1.0):
self.symbol = symbol
self.multiplier = multiplier
self.base_unit = self if base_unit is None else base_unit
return make_class(name='Unit', base=Enum, contents=locals())
Unit = make_class_Unit()
Looking at it this way, hopefully you can tell that at the time when KILOGRAM
is defined, GRAM
is really just a string. It doesn't become a Unit
instance until the last stage, where I call the (imaginary) make_class()
function.1
1Even though the make_class
function I used above doesn't actually exist under that name, it's not too different from what Python really does, which is calling the constructor of type
or a metaclass (which in this case is the metaclass for Enum
s).
DavidZ explained the problem well.
The last bit that you need to solve this problem is this: when the __init__
of each member is being run, the Enum
has been created -- so you can call it:
self.base_unit = self if base_unit is None else self.__class__(base_unit)
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With