【问题标题】:Looping through list in Python在 Python 中循环遍历列表
【发布时间】:2016-11-10 22:31:28
【问题描述】:

我有一个问题,我有一个双 for 循环,遍历一个列表。

我的问题是,一旦我得到第一个列表,并在该列表中循环,最后一项不是整数,而是一个包含 0L 的列表。

列表的最后三项如下 [...15579L, 58L, 198L]

当打印出列表中的每个元素时,我得到以下信息: ... 15579 58 198 [0L]

有谁知道这里发生了什么以及如何避免使用那个额外的项目?

这是我目前的循环:

myList1 = [[] for _ in range(accountMax+1)]
myList2 = list(myList1)
# accountMax is roughly 78000
index=0
for items in myList1:
    print('printing list')
    print(items)
    for account in items:
        print('printing account')
        print(account)
        myList2[index].append(myList1[account])
    index = index+1

这给出了 myList1 的以下输出:

printing list
[37L, 30L, 142L, 11L, 82L, 143L, 119L, 203L, 154L, 146L, 188L, 156L, 24L, 72L, 9L, 210L, 53420L, 199L, 183L, 200L, 64L, 5L, 77L, 127L, 28L, 12527L, 101L, 159L, 39L, 33203L, 161L, 42L, 197L, 208L, 187L, 17081L, 98L, 148L, 8511L, 196L, 107L, 14614L, 209L, 73L, 87L, 138L, 145L, 31L, 171L, 212L, 61L, 163L, 16L, 5512L, 158L, 110L, 133L, 124L, 100L, 76L, 204L, 84L, 69L, 150L, 202L, 139L, 192L, 5298L, 129L, 45L, 108L, 147L, 170L, 21L, 67L, 30583L, 7427L, 165L, 4762L, 56L, 29L, 26L, 44L, 181L, 11413L, 166L, 79L, 113L, 169L, 123L, 106L, 213L, 121L, 7L, 33190L, 174L, 94L, 33L, 126L, 17245L, 90L, 167L, 201L, 155L, 38L, 63L, 109L, 71L, 18L, 214L, 132L, 164L, 60L, 50L, 194L, 5280L, 103L, 62L, 8080L, 80L, 180L, 191L, 17000L, 120L, 35L, 178L, 78L, 173L, 86L, 43L, 96L, 14927L, 125L, 10L, 134L, 51L, 49L, 55L, 122L, 95L, 17087L, 207L, 26394L, 89L, 141L, 36L, 168L, 193L, 12L, 65L, 136L, 91L, 179L, 53L, 152L, 131L, 144L, 117L, 116L, 105L, 130L, 149L, 162L, 1611L, 118L, 22L, 114L, 7974L, 15896L, 189L, 172L, 182L, 59L, 88L, 27L, 75L, 13L, 2L, 92L, 14L, 57L, 195L, 32L, 215L, 46L, 112L, 17L, 52L, 74L, 70L, 4L, 54L, 1L, 20L, 83L, 186L, 81L, 19L, 140L, 2629L, 160L, 93L, 85L, 1958L, 102L, 176L, 211L, 184L, 41L, 66L, 3L, 135L, 137L, 205L, 25L, 104L, 8L, 157L,     185L, 47L, 206L, 34L, 8048L, 48L, 111L, 151L, 6L, 99L, 97L, 23L, 190L, 68L,     153L, 115L, 177L, 128L, 40L, 175L, 15L, 15579L, 58L, 198L]

打印帐户给出以下信息:

printing account
15
printing account
15579
printing account
58
printing account
198
printing account
[0L]

【问题讨论】:

  • 显示你的循环?
  • 请阅读“如何创建最小、完整且可验证的示例”(stackoverflow.com/help/mcve)。如果不看看你实际做了什么,就不可能提供帮助。
  • myList2 未定义。显示一个 myList1 值的简单示例,因为它看起来像您期望一个列表列表。 + 请与我们分享,您想如何处理您的数据
  • @solidpixel:FWIW,有一个“魔术链接”[mcve] 在 cmets 中有效。更多魔术链接请见here
  • @TemporalWolf - 有趣。 Python 一直在尝试摆脱其旧的 C 结构,例如以这种方式表示八进制。在 python 3 中,0127L 是无效的语法。我忘了它还在 2.x 中。

标签: python python-2.7 list nested-loops


【解决方案1】:

示例

>>> l = [[i] for i in range(10)]
>>> l
[[0], [1], [2], [3], [4], [5], [6], [7], [8], [9]]
>>> j = list(l)
>>> j
[[0], [1], [2], [3], [4], [5], [6], [7], [8], [9]]
>>> j[0].append(343)
>>> j
[[0, 343], [1], [2], [3], [4], [5], [6], [7], [8], [9]]
>>> l
[[0, 343], [1], [2], [3], [4], [5], [6], [7], [8], [9]]
>>>

注意当你在j 的嵌套列表中添加一些东西时会发生什么?它也附加到l

解释

这在您的代码中是如何体现的?它发生在这里:

myList2[index].append(myList1[account])

如果我们查看程序第一次循环,index 为零,并且您处于内部循环的第一次迭代中,然后是 myList2[0] == myList1[0] == items,根据我们上面看到的示例。

所以你实际上是这样做的:

items.append(myList1[account])

myList1[account] 中的列表附加到items 数组中的最后一个位置是做什么的。因此,当您打印该位置时,您会遇到一个数组而不是一个值。这也意味着在打印附加到items 的第一个列表后会出现异常,从而导致程序崩溃。

解决方案

有很多方法可以为您的代码解决此问题,但最简单的方法是创建 myList2,就像创建 myList1 一样。

myList1 = [[] for _ in range(accountMax+1)]
myList2 = [[] for _ in range(accountMax+1)]

或者

myList2 = [x[:] for x in myList1]

这样,它们都是彼此分开创建的


更好的例子

为了帮助解释我关于崩溃的观点,这里有一个程序与 OP 的功能相同:

>>> l = [[i] for i in range(10)]
>>> j = list(l)
>>> index = 0
>>> for items in l:
...     print ('printing list')
...     print (items)
...     for account in items:
...         print ('printing account')
...         print (account)
...         j[index].append(l[account])
...     index = index + 1
... 
printing list
[0]
printing account
0
printing account
[0, [...]]
Traceback (most recent call last):
  File "<stdin>", line 7, in <module>
TypeError: list indices must be integers, not list
>>> 

【讨论】:

  • 你说的没错,list() 做了一个浅拷贝。但是,它不会永远运行:只有内部列表是共享的。外部列表按预期工作。
  • @TemporalWolf 我的意思是由于items不断增长,内部循环应该永远运行
  • items 不会增长,因为myList1 不会增长。内部列表会,但除非一个是自引用的,否则它不会进入无限循环。您认为items.append(myList1[account]) 是等效的,这是不正确的:您不能在索引列表时增加列表:list[0].append 永远不会增加list 的长度,只会增加list[0] 内的长度
  • @TemporalWolf,好的,我修好了。但事实仍然是items 会增长,但是因为它现在包含列表,所以它会在打印第一个列表后使程序崩溃。此外,我认为最好尝试重新创建 OP 的代码以理解我的答案。我已经包含了一个测试程序来验证这一点
  • @smac89 感谢您的回答。我意识到 myList1 在内存不足时正在增长。我通过使用副本进行深度复制来修复它,但是在看到您的解决方案后,我认为它更优雅并使用了它。我还将它从附加更改为扩展,否则我将附加完整列表而不是列表的值。
【解决方案2】:

正如 smac89 间接指出的那样,您正在通过执行 list(myList1) 执行 myList1 的 shallow copy。这导致来自myList1myList2 的内部列表指向相同的列表:

>>> myList = [[] for _ in range(10)]
>>> nyList = list(myList)
>>> myList[0] is nyList[0]
True

它们不是等价的,它们是同一个列表。所以所有的内部列表都是共享的,而不是重复的。

这会引起很多麻烦,并且可能是您问题的根本原因。

【讨论】:

    【解决方案3】:

    由于您对 myList1 的输入数据没有任何意义,因此很难告诉您出了什么问题,但根据您的示例,我可以告诉您一些事情:

    这是您的问题区域:

    for account in items:
        print('printing account')
        print(account)
        myList2[index].append(myList1[account])
    

    因为如果您的 account 值是您提供给我们的数字:

    printing account
    15579
    

    is 表示您正在尝试从myList1 获取索引等于15579 的元素,但您不能确定它确实存在。这不是为什么可以添加零元素作为最后一个元素的原因,但这是一个严重的逻辑问题。我建议你从一开始就修复它。

    附:如果您有任何理由这样做,请向我们提供您想要做什么。它有助于我们更好地了解您的工作流程

    【讨论】:

    • 嗨。谢谢你帮忙。我还没有展示我的完整代码,但是在我开始这个双循环之前,我确保 myList1 是编号最高的帐户的大小,所以没有可能让索引超出范围。我相信我可以通过从附加切换到扩展来解决我的问题。
    猜你喜欢
    • 2018-10-26
    • 2019-04-15
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-04-01
    • 1970-01-01
    • 2014-06-26
    • 1970-01-01
    相关资源
    最近更新 更多