使用if语句终止for循环

时间:2016-11-18 01:14:37

标签: python-3.x

我不完全确定如何说出这个问题,所以我会坚持解释我的具体目标。

我正在尝试为user_input函数实现'eat'选项以进行文本冒险。我希望它检查动词是否“吃”,检查项目是否在玩家的库存中,检查项目是否可以消费,然后 - 我的目标 - 显示玩家吃掉它(并且只显示它< em>一次,见下文)。 'eat'选项目前还没有功能,我只测试打印语句。

我完全清楚下面的代码不是处理用户输入的最有效方法(我仍在调整处理意外输入的方法),所以我百分之百地批评。这只是我处理它的最初方式,我想尝试使它工作。我有一些其他的动词('去','看','带'等等)有效,我只是在'吃'时遇到很多麻烦。

def user_input(self):
    player = Player()
    while True:
        user_input = input("> ").lower()
        words = user_input.split(" ")
        wordlist = list(words)
        verb = wordlist[0]
        if len(wordlist) == 2:
            noun = wordlist[1]
            if noun not in items:
                print("Somehow '{}' isn't the right word.".format(noun))
                continue
            else:
                pass

            # The above works fine because I don't have
            # an issue with any of the other verbs regarding
            # that bit of code.
            # There's more code between these blocks to:
            # handle if the user enters a noun that is > 1 word,
            # define a few more verbs,
            # then,

        if verb == "eat":
            for item in player.inventory:
                if item.name == noun:
                    if isinstance(item, Consumable):
                        print("You eat the {}.".format(noun))
                        break
                    else:
                        print("You can't eat that!")
                        break
                else:
                    print("You don't have '{}'.".format(noun))

我不得不使用for循环(至少,我认为我必须这样做),因为我正在迭代一个包含对象的列表,而不是字符串,所以我不能只使用

if noun in player.inventory:

(我仍然尝试了百万次,但是为这个问题提出解决方案需要花费很长时间。这是我上面代码的具体示例:

class Fists(Weapons):
    def __init__(self):
        self.name = "fists"
        # more instance variables for Fists()

class LeatherWallet(Classy):
    def __init__(self):
        self.name = "leather wallet"
        # more ...

class Pizza(Consumable):
    def __init__(self):
        self.name = "pizza"
        # more ...



class Player():
    def __init__(self):
        self.inventory = [Fists(), LeatherWallet(), Pizza()]
        # other stuff

*吃拳头

You can't eat that!

*吃皮革钱包

You don't have 'leather wallet'.
You can't eat that!

*吃披萨

You don't have 'pizza'.
You don't have 'pizza'.
You eat the pizza.

从它的外观来看,它已经得到是一个简单的修复,因为它清楚地发生在迭代列表时发生了什么。我只是不知道如何(或者你是否可以)争论一个for循环使它先检查条件然后再打印。听到愚蠢的风险,我求助于你们所有人!

谢谢,如果我能更明确地提出这个问题/我的目标,请告诉我。

修改 试图在打开段落时使目标更加清晰。

3 个答案:

答案 0 :(得分:1)

你不是说你想要输出的是什么,但我最好的猜测是你不想多次说“你没有X”。

执行此操作的一种方法是使用标记,初始化为false,在找到项目时设置为true。当你离开循环时,标志会告诉你是否找到了它。

这样的事情:

    if verb == "eat":
        found = false
        for item in player.inventory:
            if item.name == noun:
                found = true
                if isinstance(item, Consumable):
                    print("You eat the {}.".format(noun))
                    break
                else:
                    print("You can't eat that!")
                    break
         if !found:
             print("You don't have '{}'.".format(noun))

答案 1 :(得分:1)

for循环有else个子句,如果循环没有中断退出则会运行。这个想法是循环正在寻找一个项目,它会在找到它时中断,else子句处理你找不到你想要的东西的默认情况。循环内部使用的变量在循环结束后仍然有效,因此找到的(或默认的)变量可用于下一位代码。

在您的情况下,如果您将最后一个else子句移出一个级别,它将仅在找不到该项时运行。在您的示例输出中,将不再打印两个“您没有'pizza1”行。

for item in player.inventory:
    if item.name == noun:
        if isinstance(item, Consumable):
            print("You eat the {}.".format(noun))
            break
        else:
            print("You can't eat that!")
            break
else:
    print("You don't have '{}'.".format(noun))
    item = None # <-- you can give a default value if you want to
                # use the variable later

在列表变大之前,循环遍历列表是可以的。然后,最好使用dict为列表编制索引,以便更快地查找。

self.inventory = dict((item.name, item) 
    for item in (Fists(), LeatherWallet(), Pizza()))

然后将for循环替换为

try:
    item = player.inventory[noun]
    if isinstance(item, Consumable):
        print("You eat the {}.".format(noun))
    else:
        print("You can't eat that!")
except KeyError:
    print("You don't have '{}'.".format(noun))

答案 2 :(得分:0)

所以,另一种方法是让这项工作,对吧?

if noun in player.inventory:
    ...

你(至少)有两种方法可以做到。

列表理解

第一个也很容易使用list comprehension

inventory_items = [item.name for name in player.inventory]

if noun in inventory_items:
    ...

那就是它。

自定义类

第二个是创建一个继承自list并覆盖__contains__方法的Inventory类,以便您可以根据需要对它们进行比较。

类似的东西:

class Inventory(list):

    def __contains__(self, item):
        """
        Override `list.__contains__`.
        """

        # First, check whether `item` is in the inventory.
        #
        # This is what a normal `list` would do.
        if list.__contains__(self, item):
            return True

        # If we couldn't find the item in the list searching
        # the "normal" way, then try comparing comparing it
        # against the `name` attribute of the items in our
        # inventory.
        for inventory_item in self:
            # Ensure we can do `inventory_item.name` so we don't get
            # an AttributeError.
            if 'name' not in dir(inventory_item):
                continue

            if inventory_item.name == item:
                return True

        return False

然后您实例化您的广告资源,如:

self.inventory = Inventory([Fists(), LeatherWallet(), Pizza()])

请注意,Inventory继承自list,因此,如果您可以执行list(x),那么您还应该能够执行Inventory(x)并获得非常相似的结果(取决于你在课堂上覆盖了多少。)

您还可以获得广告素材,并将所有项目从Item类继承,您可以在其中定义__eq__方法,并使Pizza() == 'pizza'简化Inventory比较。