社区所有版块导航
Python
python开源   Django   Python   DjangoApp   pycharm  
DATA
docker   Elasticsearch  
aigc
aigc   chatgpt  
WEB开发
linux   MongoDB   Redis   DATABASE   NGINX   其他Web框架   web工具   zookeeper   tornado   NoSql   Bootstrap   js   peewee   Git   bottle   IE   MQ   Jquery  
机器学习
机器学习算法  
Python88.com
反馈   公告   社区推广  
产品
短视频  
印度
印度  
Py学习  »  Python

IF语句给出错误的结果python[duplicate]

Michał Mazur • 3 年前 • 1279 次点击  

我有一段代码:

numbers = range(1, 50)

for i in numbers:
    if i < 20:
        numbers.remove(i)

print(numbers)

但我得到的结果是:
[2, 4, 6, 8, 10, 12, 14, 16, 18, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49]

当然,我希望20以下的数字不会出现在结果中。看来我的手机出了问题。

Python社区是高质量的Python/Django开发社区
本文地址:http://www.python88.com/topic/130188
 
1279 次点击  
文章 [ 5 ]  |  最新文章 3 年前
Cosmittus
Reply   •   1 楼
Cosmittus    3 年前

作为@Senderle答案的补充信息(仅供记录),我认为将python看到的场景背后的逻辑可视化是有帮助的 for 在一个 序列类型 ".

假设我们有:

lst = [1, 2, 3, 4, 5]

for i in lst:
    print(i ** 2)

它实际上将是:

index = 0
while True:
    try:
        i = lst.__getitem__(index)
    except IndexError:
        break
    print(i ** 2)
    index += 1

就是这样,有一种尝试-抓住机制 对于 当我们在序列类型或Iterables上使用它时(虽然有点不同——调用 next() StopIteration 例外)。

*我想说的是,python将跟踪一个名为 index 因此,无论列表发生了什么(删除或添加),python都会增加该变量并调用 __getitem__() 方法使用“this variable”并请求项。

David Hempy
Reply   •   2 楼
David Hempy    3 年前

所以我找到了一个解决方案,但它真的很笨拙。。。

首先制作一个索引数组,在其中列出所有要删除的索引,如下所示

numbers = range(1, 50)
index_arr = []

for i in range(len(numbers):
    if numbers[i] < 20:
        index_arr.append(i)

之后,您希望删除数字列表中的所有条目,并将索引保存在索引_arr中。您将遇到的问题与之前相同。因此,在从数字arr中删除一个数字后,必须从索引_arr中的每个索引中减去1,如下所示:

numbers = range(1, 50)
index_arr = []

for i in range(len(numbers):
    if numbers[i] < 20:
        index_arr.append(i)

for del_index in index_list:
    numbers.pop(del_index)

    #the nasty part
    for i in range(len(index_list)):
        index_list[i] -= 1

这会管用的,但我想这不是我们想要的方法

Moses
Reply   •   3 楼
Moses    4 年前

@senderle's 答案就是出路!

话虽如此,为了进一步说明你的问题,如果你仔细想想,你总是想删除索引0二十次:

[1,2,3,4,5............50]
 ^
[2,3,4,5............50]
 ^
[3,4,5............50]
 ^

所以你可以这样做:

aList = list(range(50))
i = 0
while i < 20:
    aList.pop(0)
    i += 1

print(aList) #[21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49]

我希望有帮助。


下面是 糟糕的做法很糟糕。

编辑(更多):

lis = range(50)
lis = lis[20:]

我也会做这项工作。

EDIT2(我很无聊):

functional = filter(lambda x: x> 20, range(50))
SorousH Bakhtiary
Reply   •   4 楼
SorousH Bakhtiary    4 年前

从列表中删除项目很简单:从列表末尾开始:

li = range(1,15)
print li,'\n'

for i in xrange(len(li)-1,-1,-1):
    if li[i] < 6:
        del li[i]

print li

后果

[1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14] 

[6, 7, 8, 9, 10, 11, 12, 13, 14]
Yassin Julian
Reply   •   5 楼
Yassin Julian    4 年前

您正在修改列表,同时对其进行迭代。这意味着第一次通过循环, i == 1 ,因此1从列表中删除。然后 for 循环转到列表中的第二项,它不是2,而是3!然后从列表中删除,然后 对于 循环转到列表中的第三项,现在是5。等等也许这样更容易形象化,用^表示 i :

[1, 2, 3, 4, 5, 6...]
 ^

这是列表最初的状态;然后删除1,循环转到列表中的第二项:

[2, 3, 4, 5, 6...]
    ^
[2, 4, 5, 6...]
       ^

等等

在迭代列表时,没有好的方法来改变列表的长度。你能做的最好的事情是:

numbers = [n for n in numbers if n >= 20]

或者,对于就地更改(parens中的东西是一个生成器表达式,在片赋值之前隐式转换为元组):

numbers[:] = (n for in in numbers if n >= 20)

如果要在移除n之前对其执行操作,可以尝试以下技巧:

for i, n in enumerate(numbers):
    if n < 20 :
        print("do something")
        numbers[i] = None
numbers = [n for n in numbers if n is not None]