rra*_*alf 6 python inheritance enums
我想扩展 Python 枚举以支持未定义的值。
我的用例:我想从 Enums 中受益(例如,能够用说话的名字来寻址/比较已知条目),但我也希望它支持未知值。如果值后面没有名称, str 应该简单地打印值的 str 表示并且比较应该失败。
让我给你一个简短的例子,我想要什么:
from enum import Enum
class Foo(Enum):
A = 1
B = 2
C = 3
def __str__(self):
return self.name
print(Foo(1)) # prints 'A'
print(Foo(2)) # print 'B'
print(Foo(3)) # prints 'C'
print(Foo(1) == Foo.A) # prints 'true'
print(Foo(4)) # I'd expect '4'
print(Foo(123)) # I'd expect '123'
print(Foo(123) == Foo.A) # I'd expect False
Run Code Online (Sandbox Code Playgroud)
当然,最后几行失败了。
有没有办法扩展枚举,或者是否有另一种简单的 Pythonic 方法?(请不要使用第三方库。)
这是适用于 Python 3.6、3.7和3.8的另一个答案。
它涉及奇怪的元类黑客行为,所以要小心。
import enum
class TestMeta(enum.EnumMeta):
def __call__(cls, value, names=None, *, module=None, qualname=None, type=None, start=1):
if names is not None:
# the enum is being constructed via the functional syntax
return super().__call__(value, names=names, module=module, qualname=qualname, type=type, start=start)
try:
# attempt to get an enum member
return super().__call__(value, names=names, module=module, qualname=qualname, type=type, start=start)
except ValueError:
# no such member exists, but we don't care
return value
class Test(enum.Enum, metaclass=TestMeta):
A = 5
B = 6
print(Test(5), Test(6), Test(7))
Run Code Online (Sandbox Code Playgroud)
该版本适用于 Python 2.7,但需要第三方库enum(请参阅评论):
class TestMeta(enum.EnumMeta):
def __call__(cls, value, names=None, module=None, type=None, start=1):
if names is not None:
return enum.EnumMeta.__call__(cls, value, names, module, type, start)
try:
return enum.EnumMeta.__call__(cls, value, names, module, type, start)
except ValueError:
return value
Run Code Online (Sandbox Code Playgroud)