我最近发现您可以在Python中使用枚举,但是我对我的代码的工作方式不满意,我想知道是否有更干净的方法来实现它。
from enum import Enum
class Hex:
def __init__(self, hex_code: str):
self.code = hex_code
class Rgb:
def __init__(self, R: int, G: int, B: int):
self.r = R
self.g = G
self.b = B
class Color(Enum):
HEX = Hex
RGB = Rgb
def main():
hex_color = Color.HEX.value('#00FF00')
rgb_color = Color.RGB.value(255, 255, 255)
if __name__ == "__main__":
main()
在此示例中,我必须通过调用.value()
枚举方法来实例化。但是当您正常实例化一个类时,您要做的只是Class(value)
。是否有可能实现类似于具有类的枚举变量的东西?
例如:
Color.HEX('#00FF00')
# Instead of:
Color.HEX.value('#00FF00')
答案 0 :(得分:3)
HEX
和RGB
不是类;它们是Color
的实例。 (enum
使用的元类会严重滥用class
语句。)您可以使用这些实例的value
属性来获取“分配”给这些名称的值。
为了使Color.HEX('#00ff00')
返回类Hex
的实例,您需要定义Color.__call__
。 (顺便说一句,请注意,您可以在定义class
的{{1}}语句内简单地定义两个类,而不是在外部定义它们。Color
语句只是一个花哨的赋值语句,位于心脏。)
class
然后
from enum import Enum
class Color(Enum):
class HEX:
def __init__(self, hex_code: str):
self.code = hex_code
class RGB:
def __init__(self, R: int, G: int, B: int):
self.r = R
self.g = G
self.b = B
def __call__(self, *args):
return self.value(*args)
没有>>> Color.HEX('#00ff00')
<__main__.Color.HEX object at 0x108740f28>
的继承值被覆盖,因此不需要立即在其定义中使用类似__call__
的值。如果您认为需要支持多重继承,那可能会改变,但是考虑到super().__call__(*args)
使用了自定义元类,我将声明处理此问题之外的内容。
答案 1 :(得分:1)
在您的问题中,我没有发现需要使用Enum
或从中受益。
Check this,了解使用Enum
的准则。
Enum
确实提供了简单的成员资格测试,因此您可以这样做:
hex_value is rgb_value
或
hex_value in Color
使用aenum
1 库,您的代码如下所示:
from aenum import Enum, extend_enum
class Color(Enum):
#
def __new__(cls, value):
member = object.__new__(cls)
member._value_ = value
member.hex = hex(value)[2:]
r, value = divmod(value, 1 << 16)
g, value = divmod(value, 1 << 8)
b = value
member.red = r
member.green = g
member.blue = b
member.rgb = r, g, b
return member
#
@classmethod
def _missing_(cls, value):
# r, g, b = value
name = 'rgb:%r' % (value, )
# name = 'rgb:%r' % ((r << 16) + (g << 8) + b, )
extend_enum(cls, name, value)
return cls[name]
#
@classmethod
def from_hex(cls, value):
# on leading #
red = int(value[:2], 16)
green = int(value[2:4], 16)
blue = int(value[4:], 16)
value = (red << 16) + (green << 8) + blue
return cls(value)
#
@classmethod
def from_rgb(cls, red, green, blue):
value = (red << 16) + (green << 8) + blue
return cls(value)
#
RED = 255 << 16
GREEN = 255 << 8
BLUE = 255
并在使用中:
>>> list(Color)
[<Color.RED: 16711680>, <Color.GREEN: 65280>, <Color.BLUE: 255>]
>>> Color.from_rgb(255, 0, 0)
<Color.RED: 16711680>
>>> Color.from_hex('00FF00')
<Color.GREEN: 65280>
>>> Color.from_hex('15A97F')
<Color.rgb:1419647: 1419647>
>>> Color.from_rgb(21, 169, 127)
<Color.rgb:1419647: 1419647>
>>> Color.from_hex('15A97F') is Color.from_rgb(21, 169, 127)
True
您当然可以更改repr()
的详细信息,存储的属性(red
,green
,blue
,hex
,{{ 1}}等。
1 披露:我是Python stdlib Enum
,enum34
backport和Advanced Enumeration (aenum
)库的作者。