【问题标题】:Index Error: List Index out of range索引错误:列表索引超出范围
【发布时间】:2013-05-24 03:39:14
【问题描述】:

这是我第一次在 stackoverflow 上发帖,所以我希望我在网站礼仪方面做的一切都是正确的。我正在上初级编程课程(Python),我目前的任务是在给定用户输入的情况下计算碳、氢和氧化合物的分子量。它可以是任何东西,从 C2 到 C8H19O2,等等。

我有我的代码,但我不断收到一个我不熟悉的错误。本质上,我要做的是让代码逐个字符地读取输入的复合字符,确定它是否是分子。然后,它读取前一个字符右侧的字符以确定它是否是另一个复合词的数字。如果它是不同的化合物,则将先前的单一化合物添加到它的总分子的运行计数中。如果是数字,则读取右边的下一个字符,再次判断是数字还是字符。如果是数字,它将前一个字符数乘以 10,然后加上下一个,以此类推,直到到达下一个字符(C123H2 将是 10*1 + 2 后跟 10*12 + 3,然后它将在运行计数中增加 123 个碳)。一旦我们的流动计数完成,然后该数字乘以每个的分子量。我不断收到一个索引错误,说我的列表索引超出范围。非常感谢任何帮助!

def main():

C1 = 0
H1 = 0
O1 = 0
num = 0

chemicalFormula = (input("Enter the chemical formula, or enter key to quit: "))
while True:
    cformula = list(chemicalFormula)
    for index, x in enumerate(cformula):
        if x == 'C':
            if cformula[index + 1] == 'H' or cformula[index + 1] == 'O':
                C1 += 1
            else:
                for index, y in enumerate(range(index + 1, 1000000000)):
                    if cformula[index + 1] != 'H' or cformula[index + 1] != 'O':
                        num = int(y)
                        num = num*10 + int(cformula[index + 1])
                    else:
                        C1 += num
                        break
        elif x == 'H':
            if cformula[index + 1] == 'C' or cformula[index + 1] == 'O':
                H1 += 1
            else:
                for y in range(index + 1, 1000000000):
                    if cformula[index + 1] != 'C' or cformula[index + 1] != 'O':
                        num = int(y)
                        num = num*10 + cformula[index + 1]
                    else:
                        H1 += num
                        break
        elif x == 'O':
            if cformula[index + 1] == 'C' or cformula[index + 1] == 'H':
                O1 += 1
            else:
                for y in range(index + 1, 1000000000):
                    if cformula[index + 1] != 'C' or cformula[index + 1] != 'H':
                        num = int(y)
                        num = num*10 + cformula[index + 1]
                    else:
                        O1 += num
                        break
        else:
            break

weightC = 15.994*C1
weightH = 1.0079*H1
weightO = 12.011*O1

sumWeight = weightC + weightH + weightO
print("The molecular weight is ", sumWeight)

【问题讨论】:

    标签: python indexing


    【解决方案1】:

    您有几个名为 index 的不同变量,它们相互隐藏。

    首先,您正在迭代 cformula:

    for index, x in enumerate(cformula)
    

    好的。所以index 总是在cformula 的合理范围内。但在那之后你就这样做了

    for index, y in enumerate(range(index + 1, 1000000000))
    

    现在索引可以是1000000000,那么:

    if cformula[index + 1]
    

    哎呀。 cformula 的大小甚至不接近 1000000002,因为它需要对这个表达式进行合理的评估。我相信你在这里并不需要enumerate

    您所要做的就是使用x(主迭代中的当前元素)访问cformula。只要您只是阅读它(这是您真正需要的),就可以了。

    从这个问题看来,您似乎不明白 enumerate 到底是什么意思 - 您在实际上不需要任何特别的地方使用它。

    不要用同一个变量来表示不同的东西!

    【讨论】:

    • 好的,我会做一些修改,看看我想出了什么!感谢您的快速响应
    • 我正在和一个朋友一起工作,他告诉我使用枚举,说实话也不太清楚这意味着什么哈哈。我对 Python 很陌生,我们的老师分配了这个程序,这个程序非常难,与我们迄今为止所学的任何东西都没有关系,所以我在这里处于未知领域。
    • @YotamKasznik 如果您需要索引,则使用range,如果您只需要值,则使用普通可迭代(例如列表)。如果两者都需要,请使用 enumerate
    【解决方案2】:

    首先,这种方法对于初学者来说看起来不错,竖起大拇指!现在,从标题中回答您的问题,错误来自访问不存在的序列元素,例如四个元素序列的第五个元素。在您的情况下,我猜这是由cformula[index + 1] 触发的,其中索引可能已经是最后一个元素的索引。请注意,知道哪个输入触发了此错误也很有趣,我猜是“CO”或“C2H5OH”,因为两者都有一个复合字母,末尾没有数字。

    现在,如何绕过它?一种非常简单的方法是简单地获取字符串的其余部分(可以为空)并处理其内容。

    count = ''
    for d in cformula[index + 1:]:
        if d.isdigit():
            count += d
        else:
            break
    

    此代码存储cformula[index] 之后的所有数字,直到下一个非数字。如果没有数字,则存储一个空字符串。请注意,这甚至不关心您正在查看哪个原子(C、H、O),因此它是您可以移动到单独函数的代码的一个很好的示例。然后,在调用该函数后,您检查数字字符串:

    if count == '':
        # number of atoms is implicitly 1
        atoms = 1
    else:
        # number of atoms is explicitly given
        atoms = int(count)
    # TODO: discard len(count) elements from the input string
    

    顺便说一句:有一个dict 类型可以用来存储每个元素的原子数。同样,您可以使用它来存储每种原子类型的权重:

    atom_weight = {'C': 15.994,
                   'H': 1.0079,
                   'O': 12.011,}
    
    weight = atom_weight['C'] * C1 + atom_weight['H'] * H1 + atom_weight['O'] * O1
    

    这不会使您的代码正确,但可以更容易地将其扩展到元素周期表的其余部分。 :)

    【讨论】:

      猜你喜欢
      • 2021-05-12
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2017-10-30
      • 1970-01-01
      • 1970-01-01
      • 2018-02-07
      相关资源
      最近更新 更多