Python 3 ValueError 从列表中删除

Posted

技术标签:

【中文标题】Python 3 ValueError 从列表中删除【英文标题】:Python 3 ValueError deleting from list 【发布时间】:2013-05-20 23:47:12 【问题描述】:

我正在使用 Python 3 和 PySide 创建一个新游戏。该游戏是游戏密码的简单 UI,基本上从列表中提取一个随机值,显示它,一旦完成值(单词),从列表中删除该单词,以免使用两次。奇怪的问题是 GUI 一次只允许选择 4 个单词,然后抛出一个 ValueError,说列表是空的,这显然是错误的,因为你只经历了 4 个单词才会得到错误。

#!/usr/bin/python

import sys
from PySide import QtCore, QtGui
from random import *

from game_gui import Ui_main_window
from game_list import cards




class game_window(QtGui.QWidget, Ui_main_window):
    def __init__(self, parent=None):
        super(game_window, self).__init__(parent)

        self.setupUi(self)

        global password_label
        password_label = self.password_label

        global get_button
        get_button = self.get_button
        get_button.clicked.connect(self.button_clicked)


    def label_clear(self):
        password_label.setText('Push Button To Get New Word')
        get_button.setText('Push Me To Get A Word')
        get_button.clicked.connect(self.button_clicked)

    def button_rename(self):
        get_button.setText('Push To Clear Word')
        get_button.clicked.connect(self.label_clear)


    def button_clicked(self):
        card_to_play = choice(cards)

        password_label.setText(card_to_play)
        cards.remove(card_to_play)
        self.button_rename()


if __name__ == "__main__":
    app = QtGui.QApplication(sys.argv)
    window = game_window()
    window.show()
    sys.exit(app.exec_())

错误是:

Traceback (most recent call last):
  File "/usr/lib/python3.3/random.py", line 249, in choice
    i = self._randbelow(len(seq))
  File "/usr/lib/python3.3/random.py", line 225, in _randbelow
    r = getrandbits(k)          # 0 <= r < 2**k
ValueError: number of bits must be greater than zero

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
  File "game_code.py", line 58, in button_clicked
    card_to_play = choice(cards)
  File "/usr/lib/python3.3/random.py", line 251, in choice
    raise IndexError('Cannot choose from an empty sequence')
IndexError: Cannot choose from an empty sequence

这两个错误都出现了大约 50 次。

非常感谢任何帮助。

编辑:根据要求,这是列表。

cards = [
    'scripture',
    'miracle',
    'garment',
    'prophecy',
    'tomb',
    'staff',
    'spirit',
    'garden of eden',
    'heaven',
    'sulpher',
    'nephelim',
    'knowledge',
    'armageddon',
    'plague',
    'commandment',
    'sovereignty',
    'resurrection',
    'wine',
    'cherub',
    'sandals',
    'wilderness',
    'gehena',
    'famine',
    'temple',
    'passover',
    'baptism',
    'leprosy',
    'ark',
    'drachma',
    'pharaoh',
    'levites',
    'scroll',
    'chaff',
    'boils',
    'Holy Spirit',
    'dragon',
    'lots',
    'Babylon',
    'tent',
    'parable',
    'scales',
    'Urim & Thummim',
    'scarlet',
    'transfiguration',
    'flame',
    'wild beast',
    'straw',
    'Red Sea',
    'pearl',
    'emerald',
    'swine',
    'demon',
    'Tartarus',
    'wine',
    'turtledove',
    'gnat',
    'camel',
    'garment',
    'shroud',
    'tomb',
    'Most Holy',
    'curtain,'
    'olive branch',
    'dust',
    'Cherub',
    'bull',
    'scorpion',
    'Nephilim',
    'privy',
    'sacrifice',
    'earthquake',
    'abyss',
    'fasting',
    'stake',
    'sling',
    'Samson',
    'Goliath',
    'betrayer',
    'slanderer',
    'murderer',
    'circumcision',
    'astrologer',
    'Hades',
    'chariot',
    'cistern',
    'balsalm',
    'undergarment',
    'bruise',
    'shipwreck',
    'fish',
    'intestines',
    'conscience',
    'curtain',
    'hypocrisy',
    'whitewash',
    'grave',
    'spear',
    'breastplate',
    'helmet',
    'leviathan',    
    ]

【问题讨论】:

你为什么在这里使用global 语句?你不能到处使用self.get_buttonself.password_label 吗? @MartijnPieters 已修复,谢谢 【参考方案1】: 当这种情况发生时,

cards显然为空。

len(seq) 然后是0,导致ValueError,但它是另一个例外,IndexError,您必须担心。

您的代码会立即在同一个函数中删除单词,而不是稍后,因此每次调用 button_clicked() 时,您都会从 cards 中删除一个随机元素。

Demo 展示了一个空列表的异常:

>>> from random import choice
>>> choice([])
Traceback (most recent call last):
  File "/opt/local/Library/Frameworks/Python.framework/Versions/3.3/lib/python3.3/random.py", line 249, in choice
    i = self._randbelow(len(seq))
  File "/opt/local/Library/Frameworks/Python.framework/Versions/3.3/lib/python3.3/random.py", line 225, in _randbelow
    r = getrandbits(k)          # 0 <= r < 2**k
ValueError: number of bits must be greater than zero

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "/opt/local/Library/Frameworks/Python.framework/Versions/3.3/lib/python3.3/random.py", line 251, in choice
    raise IndexError('Cannot choose from an empty sequence')
IndexError: Cannot choose from an empty sequence

您必须通过调试语句找出为什么您的列表被清空的速度比您想象的要快。

请注意,您正在操作一个 全局 列表,因此从该列表中删除选项不会在您完成游戏时恢复它们。随着单词被删除,您的列表将继续缩小,直到为空。

也许您想跟踪您改用了哪些词。将您使用的卡片存放在一组中:

class game_window(QtGui.QWidget, Ui_main_window):
    def __init__(self, parent=None):
        super(game_window, self).__init__(parent)

        self.used = set()

        # rest of your `__init__`

    # ...

    def button_clicked(self):
        while True:
            card_to_play = choice(cards)
            if card_to_play not in self.used:
                break
            if not set(cards).difference(self.used):
                raise ValueError('Not enough cards, used , can pick from '.format(len(self.used), len(set(cards))))

        password_label.setText(card_to_play)
        self.used.add(card_to_play)
        self.button_rename()

现在cards 保持不变,每个新的game_window 都会有一个新的空used 设置来填充。或者,您可以在想要重新开始游戏时重置used(使用self.used = set() 将其设置为新的、新鲜的、空的集合)。

【讨论】:

这行得通,但是大约在第 4 个单词之后,游戏变慢了,现在卡住了?不会抛出错误,但它变得无法使用,需要在第 4 个单词后强制退出。嗯,4号好像有点特别…… @SpencerCaesare:那么您的cards 列表只有 4 项小项。我添加了一个调试语句,测试已用和卡片的长度,如果您使用了所有卡片,则抛出异常。 @MartijnPieters 抱歉,说到 python,我是个新手。添加该更改时,它会引发无效的语法错误,说 password_label.setText(card_to_play) 无效,指向标签中的“l”... @SpencerCaesare:这意味着在上一行中缺少一个括号。我的错误,现在更正了。 @MartijnPieters 输出到控制台:Traceback (most recent call last): File "game_code.py", line 65, in button_clicked raise ValueError('Not enough cards, used , can pick from '.format(len(self.used), len(set(cards)))) ValueError: Not enough cards, used 96, can pick from 96

以上是关于Python 3 ValueError 从列表中删除的主要内容,如果未能解决你的问题,请参考以下文章

获取ValueError:list.remove(x):x尝试从列表中删除值时不在列表中

当我尝试从列表中删除元素时,如何忽略 ValueError?

无法将列表转换为数组:ValueError:只有一个元素张量可以转换为 Python 标量

在 python 中,使用 lambda 将空列表添加到数据框列会引发 valueError

Python:ValueError:需要多于0个值才能解包

在 Python 2 中,无论列表的内容如何,​​如何按值而不是引用复制复杂嵌套元素的列表