遍历数字并评估数字是否可以被某些数字整除

loop through numbers and evaluate if numbers are divisible by certain numbers

我编写了一个程序来评估特定范围内的哪些数字只能被特定数字整除(在 19 范围内)。到目前为止,代码似乎可以正常工作,但我在 pythontutor http://www.pythontutor.com/visualize.html#mode=edit 上测试了它所执行的步骤,但发生了一些奇怪的事情。

在第二个循环中,代码并不总是检查所有值 (k) 的整除性,但有时会遗漏最后一个值 (k)。 最好给你举个例子:

Liste = []
for i in range (1500, 1700):
    if i%5 == 0 and i%7 == 0:
        Liste.append(i)
print (Liste)

Teiler = [2, 3, 4, 6, 8, 9]
for k in Liste:
    z = 0
    for w in range (len(Teiler)):
        if k%Teiler[z] == 0:
            Liste.remove(k)
            z += 1
            break
        else:
            z += 1

print (Liste)

这里输出如下:

[1505, 1540, 1575, 1610, 1645, 1680]

[1505, 1575, 1645]

它的输出应该是,因为在第二个列表中只有可以被 57 整除的数字。同样在 pythontutor 上,第二个 for 循环遍历所有值 (k).

但是当我像下面这样更改数字范围时(第 2 行,将范围从 1700 更改为 1800):

Liste = []
for i in range (1500, 1800):
    if i%5 == 0 and i%7 == 0:
        Liste.append(i)
print (Liste)

Teiler = [2, 3, 4, 6, 8, 9]
for k in Liste:
    z = 0
    for w in range (len(Teiler)):
        if k%Teiler[z] == 0:
            Liste.remove(k)
            z += 1
            break
        else:
            z += 1

print (Liste)

输出结果如下:

[1505, 1540, 1575, 1610, 1645, 1680, 1715, 1750, 1785]

[1505, 1575, 1645, 1715, 1785]

如果我在 pythontutor 上 运行 这段代码,代码在 k = 1750 处停止并且不检查 k = 1785

为什么会这样? pythontutor 的检查有问题吗? 还是我的代码有问题?

我想了解为什么 Python 正在做它所做的事情。

非常感谢您的帮助。如果这是一个菜鸟问题或者我遗漏了一些明显的问题,我很抱歉。

您的问题出在这一行:

Liste.remove(k)

因为您要从用于 for 循环的同一个列表中删除元素,所以当您删除一个元素时,列表会变短,但下一次迭代您将跳转一个元素。

我建议使用两个列表或使用 while 循环,当您从列表中删除元素时,您不会进入下一次迭代,并且减少列表的长度 1;示例:

Liste = []
for i in range (1500, 1800):
    if i%5 == 0 and i%7 == 0:
        Liste.append(i)
print (Liste)

Teiler = [2, 3, 4, 6, 8, 9]

l=len(Liste)
i=0
while i<l:
    k=Liste[i]
    z = 0
    for w in range (len(Teiler)):
        if k%Teiler[z] == 0:
            Liste.remove(k)
            l-=1
            i-=1
            z += 1
            break
        else:
            z += 1
    i+=1

这段代码可以改进,但只是为了让您了解如何做到这一点

不要从您迭代的列表中删除项目,如其他答案所述。改变列表的长度会影响迭代。示例:

>>> L=list(range(10))
>>> for i in L:
...   if i==5: L.remove(i)
...   print(i)
...
0
1
2
3
4
5  # removed 5, and skipped 6!
7
8
9

也从未使用过 w,尽管 z 是等效的。相反,直接遍历 Teiler 并将项目添加到新列表(如果它满足您的条件):

Liste = []
for i in range (1500, 1800):
    if i%5 == 0 and i%7 == 0:
        Liste.append(i)
print (Liste)

Liste2 = []
Teiler = [2, 3, 4, 6, 8, 9]
for k in Liste:
    for w in Teiler:
        if k % w == 0:
            break
    else:
        Liste2.append(k)

print(Liste2)

输出:

[1505, 1645, 1715]

如果您还没有看到 for/else,则 else 仅在您不从 for 循环中中断时才执行,因此所有 k % w != 0 都必须是真实的。

另一种选择是使用list comprehensions,这确实简化了代码:

L = [i for i in range(1500,1800) if i%5 == 0 and i%7 == 0]
L = [x for x in L if all(x % k != 0 for k in (2,3,4,6,8,9))]
print(L)

输出:

[1505, 1645, 1715]

注意 1575 和 1785 可以被 3 整除,因此您的两个示例列表都存在删除列表中值的错误。