Search code examples
pythonflags

How to Update the Contents of an "enum Flag" Instance using an Internal Class Method?


Good evening fellow coders,

I'm currently working on a python-based project that uses flags, for which I use the Flag class from the enum library.

What I am struggling to do, is update the contents of an instance value, purely with the use of an internal class method. To better explain, please refer to the following simplified class example:

from enum import Flag, auto

class MyFlags(Flag):
  Null = auto()
  A = auto()
  B = auto()
  C = auto()
  D = auto()

  @classmethod
  @property
  def Class(cls):
    return cls

  def get_flag_list(self):
    """create a list of flags contained within the instance"""
    _outputList = []
    for flag in self.Class:
      if flag in self:
        _outputList.append(flag)
    return _outputList

  def update(self, givenFlags):
    """EXAMPLE: update instance contents using the contents of the passed variable"""
    if not isinstance(givenFlags, self.Class):
      raise TypeError(f"\"update\" method requires a class of type {self.Class}!")
    _compare = givenFlags.get_flag_list()
    print(f"--- flags before: {self}")  # print check before
    for flag in _compare:
      if flag not in self:
        self ^= flag                    # bit-wise xor command to add flag
    print(f"--- flags after: {self}")   # print check after

Using this class, I instantiate two flag variables:

x = MyFlags.A | MyFlags.B
y = MyFlags.B | MyFlags.C | MyFlags.D

I then try to update the contents of the instance x through the use of its internal update method, and print its contents both before and after the update call:

print(x)
x.update(y)  # also prints the before/after contents of the instance
print(x)

What I expect, is for the update method to work like the update method used with the pythonic set type, in which the method has no return value, yet still updates the contents of the calling instance. Instead, the aforementioned code results in the following output:

MyFlags.B|A

--- flags before: MyFlags.B|A

--- flags after: MyFlags.D|C|B|A

MyFlags.B|A

As seen above, the self call of the instance was correctly updated within the method, yet the changes were discarded after the method finished its execution.

I know it is possible to return self from the update method, and reassign the instance of x, as follows:

x = x.update(y)

If at all possible, I would like to avoid a return value for this method.

Any insight would be greatly appreciated!

R.Fox


Solution

  • Thanks to @juanpa.arrivillaga in the comments for pointing me in the right direction!

    juanpa.arrivillaga, June 20, 8:57

    ... nowhere in the method do you mutate the instance... enum instances are meant to be immutable. That is one of their core features...

    As the Enum and Flag classes are immutable, my attempt at reassigning the instance's value from within the instance was the wrong approach. Having refreshed my memory on mutable an immutable objects through the official python documentation, I believe I only have 3 courses of action:

    1. make use of the return value of the method to replace the old variable with a completely new instance
    2. attempt to change the attributes of the base class and make it mutable
    3. create a self-defined Flag class with the functionality I need (which might be a fun exercise!)