执行一段自定函数,但没有得到预期的回传

def send_messages(lis):

    for lis2 in lis:
        lis2 = lis.pop()
        print(lis2)
        messages.append(lis2)
    print(lis)
    print(messages)

上面这部分是函数,然后我按照如下执行了程序

lis = ['Hello!', 'How are you?', 'Thank you!']
messages = []

send_messages(lis)

得到的是

Thank you!
How are you?
['Hello!']
['Thank you!', 'How are you?']

为什么列表lis没有被移空?
而当我将函数更改为如下时:

def send_messages(lis):

    while lis:
        lis2 = lis.pop()
        print(lis2)
        messages.append(lis2)
    print(lis)
    print(messages)

执行了同样的命令,得到的却是:

Thank you!
How are you?
Hello!
[]
['Thank you!', 'How are you?', 'Hello!']
Jason990420
最佳答案

这么说吧, for lis2 in lis:,

  • 1st Loop: lis['Hello!', 'How are you?', 'Thank you!'], lis2 = lis[0]
  • 2nd Loop: lis['Hello!', 'How are you?'], lis2 = lis[1]
  • 3rd Loop: lis['Hello!'], lis2 = lis[2], 不存在, 回圈结束 所以回圈只执行两次, 每一回圈, lis2 = lis.pop() 取最后一个, 所以打印了
Thank you!
How are you?

回圈结束后print(lis), print(messages), 这时lis['Hello!'], 而messages为两次后lis 后面取出的内容, 也就是['Thank you!', 'How are you?'].

['Hello!']
['Thank you!', 'How are you?']
2年前 评论
讨论数量: 5

listpop方法是默认移除列表中最后一个元素,并且返回该元素的值,所以第一次的send_messages方法中输出的lis2由遍历的第0个元素Hello被赋值为最后一个元素Thank you!,由于遍历的时候将列表最后一个元素删除了所以列表只遍历了两次,最后lis列表只剩下元素Hello,列表message中存放的是lis2被赋值的'Thank you!''How are you?'。改成while循环后,当列表lis本身为空的时候停止循环所以得到了对应的结果。造成两次的差异主要是由于列表是可变的数据类型,在你循环的过程中列表lis本身也在发生改变!

2年前 评论
Jason990420

本问题中, 在for 回圈中, 是以迭代列表的方式来作回圈的, 迭代列表内容改变了, 自然迭代的结果也改变了; 而while 回圈只以列表是否为空列表, 并不是以索引作为判断, 自然不受影响.

  1. 基本上来说, 在 for 回圈中的迭代列表是不可以在回圈改变其内容的, 否则可能会出现不可预期的结果.

  2. 因此一般来说会用复制一个列表来作为回圈中的迭代列表, 如果该列表的内容是不可改变, 使用浅层复制 (Shallow Copy), 否则必须使用深层复制 (Deep Copy).

  3. 问题中列表的内容都是字符串, 属不可改变内容, 所以使用浅层复制即可, 如list.copycopy.copy, 当然使用深层复制也可以, 如copy.deepcopy.

def send_messages(lis):

    for lis2 in lis.copy(): # 浅层复制
        lis2 = lis.pop()
        print(lis2)
        messages.append(lis2)
    print(lis)
    print(messages)
2年前 评论

@SilenceHL 我还是不太懂为什么最后‘Hello’没有被移出

2年前 评论
Jason990420

这么说吧, for lis2 in lis:,

  • 1st Loop: lis['Hello!', 'How are you?', 'Thank you!'], lis2 = lis[0]
  • 2nd Loop: lis['Hello!', 'How are you?'], lis2 = lis[1]
  • 3rd Loop: lis['Hello!'], lis2 = lis[2], 不存在, 回圈结束 所以回圈只执行两次, 每一回圈, lis2 = lis.pop() 取最后一个, 所以打印了
Thank you!
How are you?

回圈结束后print(lis), print(messages), 这时lis['Hello!'], 而messages为两次后lis 后面取出的内容, 也就是['Thank you!', 'How are you?'].

['Hello!']
['Thank you!', 'How are you?']
2年前 评论

@Jason990420 了解,明白了。

2年前 评论

讨论应以学习和精进为目的。请勿发布不友善或者负能量的内容,与人为善,比聪明更重要!