Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/python/333.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
如何创建自引用Python3枚举?_Python_Python 3.6 - Fatal编程技术网

如何创建自引用Python3枚举?

如何创建自引用Python3枚举?,python,python-3.6,Python,Python 3.6,我可以创建一个枚举类RockPaperScissors,这样ROCK.value==“ROCK”和ROCK.beats==SCISSORS,其中ROCK和SCISSORS都是RockPaperScissors中的常量吗?你试过了吗 from enum import IntEnum class RPS(IntEnum): Rock = 1 Paper = 2 Scissor = 3 RPS.Rock.beats = RPS.Scissor RPS.Paper.bea

我可以创建一个枚举类
RockPaperScissors
,这样
ROCK.value==“ROCK”
ROCK.beats==SCISSORS
,其中
ROCK
SCISSORS
都是
RockPaperScissors
中的常量吗?

你试过了吗

from enum import IntEnum

class RPS(IntEnum):
    Rock = 1 
    Paper = 2 
    Scissor = 3

RPS.Rock.beats = RPS.Scissor
RPS.Paper.beats = RPS.Rock
RPS.Scissor.beats = RPS.Paper

for i in [RPS.Rock,RPS.Paper,RPS.Scissor]:
    print(i, "beats", i.beats)
输出:

RPS.Rock beats RPS.Scissor
RPS.Paper beats RPS.Rock
RPS.Scissor beats RPS.Paper
对。你可以


在python中,所有(*)对象都是对象,您可以将更多属性附加到它们上:

def func():
    pass

func.result = 42

print(func.result)  # 42


*)很少有例外情况适用

这样的情况怎么样:

from enum import IntEnum

class RPS(IntEnum):
    Rock = 1
    Paper = 2
    Scissor = 3

    def __lt__(self, other):
        if self == RPS.Scissor and other == RPS.Rock:
            return True
        if self == RPS.Rock and other == RPS.Scissor:
            return False
        return self.value < other.value

    def __gt__(self, other):
        if self == RPS.Rock and other == RPS.Scissor:
            return True
        if self == RPS.Scissor and other == RPS.Rock:
            return False
        return self.value > other.value
from itertools import combinations
members = list(RPS)
for pair in combinations(members, 2):
    print(f'{pair[1].name} < {pair[0].name} ? {pair[1] < pair[0]}')
    print(f'{pair[0].name} < {pair[1].name} ? {pair[0] < pair[1]}')

    print(f'{pair[1].name} > {pair[0].name} ? {pair[1] > pair[0]}')
    print(f'{pair[0].name} > {pair[1].name} ? {pair[0] > pair[1]}')
从枚举导入IntEnum
RPS级(内部):
岩石=1
纸张=2
剪刀=3
定义(自身、其他):
如果self==RPS.Scissor和other==RPS.Rock:
返回真值
如果self==RPS.Rock和other==RPS.Scissor:
返回错误
返回self.valueother.value
这不是Rock.beats,但对于enum(或类)中的谁比谁更符合逻辑,这不是Rock to beat Scissor的继承属性,而是我们定义RPS的方式(如果您决定尝试其他方法,也可以采用另一种方式) 使用python方法ge(如果需要,您可以实现其余部分),您可以自然地获得如下比较:

from enum import IntEnum

class RPS(IntEnum):
    Rock = 1
    Paper = 2
    Scissor = 3

    def __lt__(self, other):
        if self == RPS.Scissor and other == RPS.Rock:
            return True
        if self == RPS.Rock and other == RPS.Scissor:
            return False
        return self.value < other.value

    def __gt__(self, other):
        if self == RPS.Rock and other == RPS.Scissor:
            return True
        if self == RPS.Scissor and other == RPS.Rock:
            return False
        return self.value > other.value
from itertools import combinations
members = list(RPS)
for pair in combinations(members, 2):
    print(f'{pair[1].name} < {pair[0].name} ? {pair[1] < pair[0]}')
    print(f'{pair[0].name} < {pair[1].name} ? {pair[0] < pair[1]}')

    print(f'{pair[1].name} > {pair[0].name} ? {pair[1] > pair[0]}')
    print(f'{pair[0].name} > {pair[1].name} ? {pair[0] > pair[1]}')
来自itertools导入组合的

成员=列表(RPS)
对于成对组合(成员,2):
打印(f'{pair[1].name}<{pair[0].name}?{pair[1]{pair[0].name}?{pair[1]>pair[0]}')
打印(f'{pair[0].name}>{pair[1].name}?{pair[0]>pair[1]}')
哪些产出:

Paper < Rock ? False
Rock < Paper ? True
Paper > Rock ? True
Rock > Paper ? False
Scissor < Rock ? True
Rock < Scissor ? False
Scissor > Rock ? False
Rock > Scissor ? True
Scissor < Paper ? False
Paper < Scissor ? True
Scissor > Paper ? True
Paper > Scissor ? False
Paper石头?真的
石头>纸?假的
剪刀石头?真的
石头剪刀?假的
剪刀>石头?假的
摇滚>剪刀?真的
剪刀<纸?假的
剪纸机?真的
剪刀>纸?真的
纸>剪刀?假的
枚举成员是该类型的实例。这意味着 您可以只使用常规属性:

from enum import Enum

class RockPaperScissors(Enum):
    Rock = "rock"
    Paper = "paper"
    Scissors = "scissors"

    @property
    def beats(self):
        lookup = {
            RockPaperScissors.Rock: RockPaperScissors.Scissors,
            RockPaperScissors.Scissors: RockPaperScissors.Paper,
            RockPaperScissors.Paper: RockPaperScissors.Rock,
        }
        return lookup[self]

通过仔细挑选成员的顺序,可以简单地将每个成员描述为使用
属性
击败前一个成员

from enum import Enum

class RPS(Enum):
    Rock = 0
    Paper = 1
    Scissor = 2

    @property
    def beats(self):
        return list(RPS)[self.value - 1]

for v in RPS:
    print(v.name, 'beats', v.beats.name)
输出
为了完整性起见,也可以这样做。它更具描述性,但需要这个
getattr
调用,就我个人而言,我不是最大的粉丝

from enum import Enum

class RockPaperScissors(Enum):

    ROCK = ("rock", "scissors")
    PAPER = ("paper", "rock")
    SCISSORS = ("scissors", "paper")

    def __init__(self, value, beats):
        self._value_ = value
        self._beats = beats

    @property
    def beats(self):
        return getattr(RockPaperScissors, self._beats.upper())

在类创建过程中,让
Enum
成员相互引用有点棘手;诀窍在于知道在将每个成员添加到
Enum
本身之前,都会创建并初始化它。这意味着您可以检查正在创建的
Enum
的状态,并对正在创建的成员和已创建的成员进行调整

这里的基本问题是在成员之间创建循环引用,我们可以通过使用每个新成员修改循环来解决这个问题:

class RPS(Enum):

    Rock = "rock"
    Paper = "paper"
    Scissors = "scissors"

    def __init__(self, value):
        if len(self.__class__):
            # make links
            all = list(self.__class__)
            first, previous = all[0], all[-1]
            first.beats = self
            self.beats = previous
在使用中:

>>> print(RPS.Rock.beats)
RPS.Scissors

>>> print(RPS.Paper.beats)
RPS.Rock

>>> print(RPS.Scissors.beats)
RPS.Paper


披露:我是、和库的作者。

为什么不使用带有属性值和beats的常规类?@DeveshKumarSingh,因为
Enum
很好地编码了相关常量集合的语义,而不是任意类。这就是说,它会比普通类简单得多吗?我可以在类内声明
beats
属性吗,还是必须在类外声明呢?@l0b0我想人们可以尝试与装饰师一起做些事情-不确定,现在没有时间去摆弄-也许谷歌搜索“flansh”似乎没有给出任何相关的解释。显然这是一个德语俚语?特里普谁会想到呢。它可能是德语——我当时的印象是它与其他东西有关系——在英语中应该是。改写答案。这种方法的一个问题是实例dict仍然是可写的——任何其他代码都可以将RPS.Rock.beats=“potato”放入其中。如果你使用属性/描述符,那么你会得到一个只读属性。我喜欢使用
\uuuu ge\uuuu
,但是Rock>剪刀应该是真的,对吧?谢谢,修正了。需要同时使用uugt_uuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuu这样一个1项元组就变成了
obj=\uuuu new\uuuu(1)
。有趣的是,你可以说,
ROCK='A',16
这将变成
obj=\uuuuuuuuu新的('A',16))
这将变成
\uuuu新的('A',16)
这将变成
ROCK.value==10
。谢谢你让我把我的故事讲清楚