在Python中使用字典替代Case/Switch语句

8
我想要对一个初始化时所有颜色都在正确面上的魔方进行随机打乱。我有旋转魔方的移动函数。我想随机选择50个移动函数来完成随机打乱。
我正在进行这个项目是为了学习更多有关Python的知识,因为我主要使用C++,而Python中没有case/switch语句,所以我尝试使用字典。当我制作字典时,代码似乎出现了某些问题:
def random_cube(self):
    scramble = {    0 : self.up_turn(),
                    1 : self.down_turn(),
                    2 : self.left_turn(),
                    3 : self.right_turn(),
                    4 : self.front_turn(),
                    5 : self.back_turn(),
                    6 : self.up_turn("inverted"),
                    7 : self.down_turn("inverted"),
                    8 : self.left_turn("inverted"),
                    9 : self.right_turn("inverted"),
                    10: self.front_turn("inverted"),
                    11: self.back_turn("inverted")
                }
    for x in range(50):
        i = random.randint(0,11)
        scramble[i]

当我创建这个字典时,它似乎会运行并执行所有11个条目(我认为是这样)。我找不到更好的方法,至少比一长串if/elif语句更优雅。
!编辑:实施两个建议后,函数的("inverted")标志都没有被设置。例如,调用1和7都给了我down_turn,但输出显示标志未被设置,而在7号时应该已经设置了。
有什么想法吗?

1
作为设计注记,魔方其实只有两种不同的转动方式。其余的只是转动面的朝向问题。编写一个函数可能更容易:def rotate(face, clockWise=True): 另外,作为使用字典和 for 循环的替代方案,您可以制作一个列表并使用 random.choice 从中选择元素。 - Joel Cornett
对于从列表中随机选择的random.choice,我也进行了一些调整。我将函数调用放在一个列表中并尝试了一下,但对我来说并不完全有效...此外,我将魔方设置为始终以白色作为“前面”面向。我认为这不是最好的表示方法:\ - d d
2个回答

16

当你定义字典时,实际上是在调用函数,并将返回值存储在字典中。如果只想让字典存储对函数的引用,您需要删除括号。所以可以这样做:

scramble = {  0: self.up_turn,
              1: self.down_turn,
              etc.

然后,在底部调用 scramble[i]()

这将不带参数地调用该函数。如果要处理将"inverted"作为参数传递的情况,您可以定义单独的函数,如up_turn_inverted()等,或者您可以让字典存储函数和参数的2元组,然后调用像 scramble[i][0](scramble[i][1]) 这样的东西。

来自评论中的建议更新:

您还可以使用 lambda 表达式来定义函数,特别是那些需要参数的函数。这基本上相当于在一个匿名函数中原地定义 up_turn_inverted 函数。它看起来像这样:

6: lambda: self.up_turn("inverted")
7: lambda: self.down_turn("inverted")

等等。


3
另一个选项是使用 lambda: 来创建反转的调用。 - Amber
1
作为一般原则,如果可能的话,应该避免对字典排序做出假设。我会投票支持lambda解决方案。 - happydave
顺便说一下,在这种情况下,使用字典并不是必需的 - 列表或元组可以节省一些打字。 - happydave
抱歉,我不清楚lambda解决方案是什么。你能提供一下吗? - machine yearning
我将其添加到答案的末尾。 - happydave
显示剩余3条评论

2
我相信这被称为“函数作为一等值”,最重要的是,您可以将引用函数的标识符作为参数传递给其他函数。
当您定义字典时,Python解释器会评估函数并将其值存储在字典中。为了推迟此操作直至生成随机数,请尝试在字典中存储函数本身的引用,方法是省略括号:
def random_cube(self):
    scramble = {    0 : self.up_turn,
                    1 : self.down_turn,
                    2 : self.left_turn,
                    3 : self.right_turn,
                    4 : self.front_turn,
                    5 : self.back_turn,
                    6 : self.up_turn,
                    7 : self.down_turn,
                    8 : self.left_turn,
                    9 : self.right_turn,
                    10: self.front_turn,
                    11: self.back_turn
                }

在for循环中调用函数时,您需要通过传递哪些参数来区分正常和反转情况:

    for x in range(50):
        i = random.randint(0,11)
        if i <= 5:
            scramble[i]()
        else:
            scramble[i]("inverted")

更简单地说:
    for x in range(50):
        i = random.randint(0,11)
        scramble[i]( () if i < 6 else ("inverted"))

谢谢回复。我没有考虑解释器必须评估才能将值放入字典中。 - d d

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接