gpt4 book ai didi

python - 我可以为我的枚举的两个不同成员使用一个别名吗

转载 作者:行者123 更新时间:2023-12-04 15:04:17 24 4
gpt4 key购买 nike

我真诚地希望,我遵守了所有规则和准则,并且我的问题/问题足够全面,可以找到合适的答案。首先,一个小介绍:
对于我当前的项目,我想为树节点对象指定特定类型。为了简单起见,我将使用颜色作为类比。

我有什么

假设我有以下枚举,派生自 enum标准库:

from enum import Enum, auto

class Colour(Enum):
CRIMSON = auto()
SCARLET = auto()
RED = auto()
BLUE = auto()

所以每个成员都有不同的值。

我想要什么

到目前为止,还不错。但我希望拥有的是:

class Colour(Enum):
CRIMSON = auto()
SCARLET = auto()
# RED = CRIMSON or SCARLET
BLUE = auto()

因此,如果我有一个具有如下属性的对象:

>>> r = Colour.SCARLET

我希望以下语句返回 True:

>>> type(r) is Colour
True
>>> r is Colour.SCARLET
True
>>> r is Colour.RED
True

当然这应该是 False:

>>> r is Colour.CRIMSON
False
>>> r is Colour.BLUE # obviously False...
False

请注意,在我的情况下,不需要能够分配类型 RED,仅分配 CRIMSONSCARLET 就足够了.

我目前(不满意)的解决方案

到目前为止我尝试的是以下内容:

class Colour(Enum):
# ... member definitions ...
def isRed(self):
return self is Colour.SCARLET or self is Colour.CRIMSON

但我发现这个解决方案相当不优雅,而且使用起来很麻烦。此外,它也没有将 CRIMSONSCARLET 的性质反射(reflect)为 RED 的阴影。

我实现的另一个解决方案涉及子调用或嵌套Colour,但在任何一种情况下我都无法满足上述所有标准,因此我没有在此处发布这些内容。

在使用枚举之前,我用整数表示每个节点的 Node.colour 属性:

# trees.py
# defining global constants
SCARLET = 1
CRIMSON = 2
BLUE = -1

class Node:
def __init__(self, parent, children, col):
self.parent = parent
self.children = children
self.colour = col # either 1, 2 or -1

所以我可以执行以下操作:

>>> x = Node(None, None, SCARLET)
>>> y = Node(None, None, BLUE)
>>> If x.colour is > 0:# do stuff...

但我发现这种方式非常不符合 Python 风格,也很不直观,因为对 REDSCARLETBLUE 等的测试经常发生这使得代码更难阅读。
此外,如果我认为没有必要,也不应使用 int 数据类型,因为这些“颜色”没有自然顺序或其他类似 int 的属性。

最佳答案

为了确保我理解:

Colour.SCARLET is Color.RED
Colour.CRIMSON is color.RED

但是

Colour.SCARLET is not Colour.CRIMSON

?

如果那是正确的,那么不,你不能拥有那个。原因是 是对象标识,并且没有变通方法或技巧可以愚弄它。这是 Python 固有的,而不是枚举特有的。

SCARLETCRIMSON 可以是 RED 的别名吗,或者它们是否具有独特的属性,其中之一是红色阴影?

可能对您有用的东西(使用 aenum library 显示,但使用 stdlib Enum 稍微做些工作就可以做到):

from aenum import Enum, auto

class PrimaryColour(Enum):
RED = auto()
GREEN = auto()
BLUE = auto()

class Shades(Enum):
#
_init_ = 'value primary'
#
CRIMSON = PrimaryColour.RED
SCARLET = PrimaryColour.RED

并在使用中:

>>> list(Shades)
[<Shades.CRIMSON: 1>, <Shades.SCARLET: 2>]

>>> Shades.CRIMSON.primary is PrimaryColour.RED
True

另一种可能性:

from enum import Enum, auto

class Colour(Enum):
#
RED = auto()
GREEN = auto()
BLUE = auto()
CRIMSON = RED
SCARLET = RED
AQUAMARINE = GREEN, BLUE
#
def is_colour(self, colour):
return colour._value_ in self.ancestors or self._value_ in colour.ancestors
#
def __new__(cls, *values):
members = list(cls)
used_values = {m.value: m for m in members}
# previous values are now in used_values; after isolating first
# value, check if it has already been used
first, *others = values
if first in used_values:
# it's an alias -- create a new value
others = (first, ) + tuple(others)
first = len(members) + 1
member = object.__new__(cls)
member._value_ = first
member.ancestors = (first, ) + tuple(others) # always it's own ancestor
return member

并在使用中:

>>> list(Colour)
[<Colour.RED: 1>, <Colour.GREEN: 2>, <Colour.BLUE: 3>, <Colour.CRIMSON: 4>, <Colour.SCARLET: 5>, <Colour.AQUAMARINE: 6>]

>>> Colour.RED
<Colour.RED: 1>

>>> Colour.CRIMSON
<Colour.CRIMSON: 4>

>>> Colour.AQUAMARINE
<Colour.AQUAMARINE: 6>

>>> Colour.CRIMSON.is_colour(Colour.RED)
True

>>> Colour.RED.is_colour(Colour.CRIMSON)
True

>>> Colour.CRIMSON.is_colour(Colour.SCARLET)
False

关于python - 我可以为我的枚举的两个不同成员使用一个别名吗,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/66445554/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com