SETUP: Python 3.8.2; Some Enum Class with an overloaded __contains__() function.
from enum import Enum
class Something(Enum):
A = 1
def __contains__(self, Other):
return Other in self.__class__.__members__.keys()
TEST 1: Using values from the enum itself.
print("A:", Something.A in Something)
works fine (here result = A: True).
TEST 2: Using non-enum values.
print("1:", 1 in Something)
fails with an exception, namely
TypeError: unsupported operand type(s) for 'in': 'int' and 'EnumMeta'
QUESTION:
How is it possible to achieve an in functionality (membership operator) where the left operand can be anything? That is, it should be possible to write something like
if anything in Something:
...
without having to check the type of anything.
Defining Something.__contains__ lets you write something like 1 in Something.A. For what you want, you would need to subclass EnumMeta and use the result in defining Something.
In some sense, Enum.__new__ already does the check we want; passing a value to the type either returns the appropriate instance, or raises a ValueError.
>>> Something.A
<Something.A: 1>
>>> Something(Something.A)
<Something.A: 1>
>>> Something(1)
<Something.A: 1>
>>> Something(3)
ValueError: 3 is not a valid Something
During handling of the above exception, another exception occurred:
Traceback (most recent call last):
[...]
So, our new metaclass's __contains__ method simply has to try to retrieve the given value from the given type, returning True if it succeeds and False if an exception is raised.
from enum import EnumMeta, Enum
class MyMeta(EnumMeta):
def __contains__(self, other):
try:
self(other)
except ValueError:
return False
else:
return True
class Something(Enum, metaclass=MyMeta):
A = 1
assert Something.A in Something
assert 1 in Something
assert 2 not in Something
If you want 1 in Something to return False instead, just catch the TypeError raised by super().__contains__.
class MyMeta(EnumMeta):
def __contains__(self, other):
try:
return super().__contains__(other)
except TypeError:
return False
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