首页 > 解决方案 > 如何在 Python 中使大量 if 语句更具可读性

问题描述

我最近练习了 python,我发现自己参与了很多关于一个简单的石头剪刀布游戏的 if 语句,它看起来像这样:我的问题是如何让我的代码更高效、更易于编写和阅读

 while True:

        player_choice = raw_input("\n1-Rock\n2-Paper\n3-Scissors\n{} choose a number:".format(name))
        player_choice = int(player_choice)

        if player_choice == 1:
            player_choice = Choices.rock
        if player_choice == 2:
            player_choice = Choices.paper
        if player_choice == 3:
            player_choice = Choices.scissors


    # Getting the cpu choice.
        cpu_choice = random.randint(1, 3)
        if cpu_choice == 1:
            cpu_choice = Choices.rock
        if cpu_choice == 2:
            cpu_choice = Choices.paper
        if cpu_choice == 3:
            cpu_choice = Choices.scissors


        if player_choice == cpu_choice:
            print"\n Its a Tie!\n!"

        if player_choice == Choices.paper and cpu_choice == Choices.rock:
            print"\n Congratulations!\n{} you won!".format(name)

        if player_choice == Choices.scissors and cpu_choice == Choices.paper:
            print"\n Congratulations!\n{} you won!".format(name)

        if player_choice == Choices.rock and cpu_choice == Choices.scissors:
            print"\n Congratulations!\n{} you won!".format(name)

        if cpu_choice == Choices.scissors and player_choice == Choices.paper:
            print"\n Too bad!\n{} you lost!".format(name)

        if cpu_choice == Choices.paper and player_choice == Choices.rock:
            print"\n Too bad!\n{} you lost!".format(name)

        if cpu_choice == Choices.rock and player_choice == Choices.scissors:
            print"\n Too bad!\n{} you lost!".format(name)*

标签: pythonpython-2.7

解决方案


您的if语句可以用字典代替。例如,Choices可以使用这样的字典将整数映射到特定属性:

choices = {1: Choices.rock, 2: Choices.paper, 3: Choices.scissors}

现在你可以使用

player_choice = choices[player_choice]

cpu_choice = random.choice(choices.values())

Choices从封装的角度来看,处理这种映射实际上应该是对象的责任。如果您要使用实际enum.Enum对象(需要 Python 3 或安装backport 包) enum34那么您可以使用:

player_choice = Choices(player_choice)

但是根据您定义的方式Choices,您可以给它一个__call__基本上使用上述映射的方法来给您相同的结果。

接下来,您可以使用字典来确定获胜者:

# if a player picks the key, and the opponent has picked the value,
# then the player wins.
wins_against = {
    Choices.rock: Choices.scissors,
    Choices.paper: Choices.rock,
    Choices.scissors: Choices.paper,
}

然后确定获胜者:

if player_choice == cpu_choice:
    print"\n Its a Tie!\n!"
elif wins_against[player_choice] == cpu_choice:
    print"\n Congratulations!\n{} you won!".format(name)
else:  # not the same, and not a win, so the player lost
    print"\n Too bad!\n{} you lost!".format(name)

但是,该映射也可能是您的Choices枚举对象的一部分;给它们一个wins_against属性:

if player_choice == cpu_choice:
    print"\n Its a Tie!\n!"
elif player_choice.wins_against == cpu_choice:
    print"\n Congratulations!\n{} you won!".format(name)
else:
    print"\n Too bad!\n{} you lost!".format(name)

如果您要使用该enum库,代码可能变为:

from enum import Enum

class Choices(Enum):
    rock = 1, 'scissors'
    paper = 2, 'rock'
    scissors = 3, 'paper'

    def __new__(cls, value, win_against):
        instance = object.__new__(cls)
        instance._value_ = value
        instance._win_against = win_against
        return instance

    @property
    def win_against(self):
        return type(self)[self._win_against]


 while True:
    options = '\n'.join(['{}-{}'.format(c.value, c.name) for c in choices])
    player_choice = raw_input("\n\n{} choose a number:".format(
        options, name))
    try:
        player_choice = int(player_choice)
        player_choice = Choices(player_choice)
    except ValueError:
        print "Not a valid option, try again"
        continue

    cpu_choice = random.choice(list(Choices))

    if player_choice is cpu_choice:
        print"\n Its a Tie!\n!"
    elif player_choice.wins_against is cpu_choice:
        print"\n Congratulations!\n{} you won!".format(name)
    else:  # not the same, and not a win, so the player lost
        print"\n Too bad!\n{} you lost!".format(name)

推荐阅读