Search code examples
pythonpython-3.xenumsenum-flags

Python IntFlags behavior for 0 item


In the below example codes which uses IntFlag of enum in Python3, I can understand the first 5 behaviors. But I cannot understand the last 3 behaviors. I think these results should be False. Can anyone elaborate on these behaviors? And any idea how can I define the CLEAR which makes the 3 results ‘False’?

In [3]: from enum import IntFlag, auto

In [4]: class Functions(IntFlag):
   ...:     CLEAR=0
   ...:     FUNC1=auto()
   ...:     FUNC2=auto()
   ...:     FUNC3=auto()
   ...:     FUNC12=FUNC1|FUNC2
   ...:     ALL=FUNC1|FUNC2|FUNC3
   ...:

In [5]: Functions.FUNC1 in Functions.FUNC12 #OK
Out[5]: True

In [6]: Functions.FUNC2 in Functions.FUNC12 #OK
Out[6]: True

In [7]: Functions.FUNC3 in Functions.FUNC12 #OK
Out[7]: False

In [8]: Functions.FUNC12 in Functions.ALL #OK
Out[8]: True

In [9]: Functions.ALL in Functions.FUNC12 #OK
Out[9]: False

In [10]: Functions.CLEAR in Functions.ALL #?
Out[10]: True

In [11]: Functions.CLEAR in Functions.FUNC12 #??
Out[11]: True

In [12]: Functions.CLEAR in Functions.FUNC1 #???
Out[12]: True

Solution

  • CLEAR represents the empty set of flags.

    The documentation never seems to explicitly mention this, but as far as I understand it, the in operator tests whether the flags on the left-hand side are a subset of the right-hand side.

    However, the source code for the Flag.__contains__ method (which is inherited by IntFlag) supports this understanding – this method implements the operation other in self:

    def __contains__(self, other):
        """
        Returns True if self has at least the same flags set as other.
        """
        if not isinstance(other, self.__class__):
            raise TypeError(
                "unsupported operand type(s) for 'in': '%s' and '%s'" % (
                    type(other).__qualname__, self.__class__.__qualname__))
        return other._value_ & self._value_ == other._value_
    

    The empty set is a subset of any other set, therefore Functions.CLEAR in Functions.x is true for any x.

    Or, in terms of the concrete bitwise operations that are performed, CLEAR is 0, so CLEAR in x evaluates 0 & x == 0 which is always true.