设置:Python 3.8.2;一些带有重载__contains__()函数的枚举类。
from enum import Enum
class Something(Enum):
A = 1
def __contains__(self, Other):
return Other in self.__class__.__members__.keys()
Run Code Online (Sandbox Code Playgroud)
测试 1:使用枚举本身的值。
print("A:", Something.A in Something)
Run Code Online (Sandbox Code Playgroud)
工作正常(这里结果= A: True)。
测试 2:使用非枚举值。
print("1:", 1 in Something)
Run Code Online (Sandbox Code Playgroud)
失败但有异常,即
TypeError: unsupported operand type(s) for 'in': 'int' and 'EnumMeta'
Run Code Online (Sandbox Code Playgroud)
问题:
如何实现in左操作数可以是任何内容的功能(成员运算符)?也就是说,应该可以写类似的东西
if anything in Something:
...
Run Code Online (Sandbox Code Playgroud)
无需检查 的类型anything。
定义Something.__contains__可以让你写出类似的东西1 in Something.A。对于您想要的,您需要子类化EnumMeta并在定义中使用结果Something。
从某种意义上说,我们想要的检查Enum.__new__ 已经完成了;将值传递给类型要么返回适当的实例,要么引发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):
[...]
Run Code Online (Sandbox Code Playgroud)
因此,我们新的元类的__contains__方法只需尝试从给定类型检索给定值,True如果成功并且False引发异常则返回。
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
Run Code Online (Sandbox Code Playgroud)
如果你想1 in Something返回False,只需抓住TypeError提出的super().__contains__。
class MyMeta(EnumMeta):
def __contains__(self, other):
try:
return super().__contains__(other)
except TypeError:
return False
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
2160 次 |
| 最近记录: |