Python: for循环无原因停止

huangapple go评论75阅读模式
英文:

Python: for loops stops without reason

问题

大家好,我写了这个简单的程序(用于学习Python),它会打印一系列消息,然后将这些消息填充到一个新的列表中。这是一个非常简单的代码,但在for循环中出了一些问题。

代码如下:

def Print_It (message):
    print (message)

def Send_mex (To_send):
    for sende in To_send:
        Print_It(sende)
        current_message = List_of_Message.pop()
        Sended_message.append(current_message)

List_of_Message = ['GO!!!', 'WAIT!!!', 'DAMN!!', 'OUCH!!!']
Sended_message = []

Send_mex (List_of_Message)
Print_It (List_of_Message)
Print_It (Sended_message)

输出是:

GO!!!
WAIT!!!
['GO!!!', 'WAIT!!!']
['OUCH!!!', 'DAMN!!']

期望的输出是:

GO!!!
WAIT!!!
OUCH!!!
DAMN!!!
[]
['OUCH!!!', 'DAMN!!','GO!!!', 'WAIT!!!']

由于某些我不理解的原因,for循环只对列表的前两个参数起作用,而不是所有的参数...

有什么建议吗?

英文:

Everyone, I wrote this simple program (to learn python) that prints a list of messages and then fills a new list of printed message. It's very easy code , but something goes wrong with for loop.

The code is :

def Print_It (message):
        print (message)
       
def Send_mex (To_send):
        for sende in To_send:
            Print_It(sende)
            current_message = List_of_Message.pop()
            Sended_message.append(current_message)

List_of_Message = ['GO!!!', 'WAIT!!!', 'DAMN!!', 'OUCH!!!']
Sended_message = []

Send_mex (List_of_Message)
Print_It (List_of_Message)
Print_It (Sended_message)

The Output is:

GO!!!
WAIT!!!
['GO!!!', 'WAIT!!!']
['OUCH!!!', 'DAMN!!']

The expected output is:

GO!!!
WAIT!!!
OUCH!!!
DAMN!!!
[]
['OUCH!!!', 'DAMN!!','GO!!!', 'WAIT!!!']

for some reasons that I don't understand the for loop works only for two arguments of list not for all...

Any suggestions?

答案1

得分: 1

你正在将要发送的消息列表传递给send_mex,因此它不需要再访问并修改list_of_message的全局名称。它应该只修改传递给它的内容。(虽然让它修改其参数也不是最佳做法,但比直接更改全局变量要好。)

全局的已发送消息队列也是如此;我建议它只返回已发送的消息。如果调用代码多次调用send_mex,则可以将这些消息追加到全局变量中。

如果在遍历列表时修改列表,for循环会中断,所以不要这样做。如果要弹出列表中的项目,只需使用一个while循环,该循环在列表的长度非零时继续执行:

def send_mex(to_send):
    sent = []
    while to_send:
        message = to_send.pop()
        print_it(message)
        sent.append(message)
    return sent

list_of_message = ['GO!!!', 'WAIT!!!', 'DAMN!!', 'OUCH!!!']
sent_message = send_mex(list_of_message)

如果附加你的最终输出代码,你会发现list_of_messages最终为空,最初在其中的项目现在在sent_message中。

你会注意到我将名称的首字母改成了小写;在标准的Python编码风格中,首字母大写通常用于常量,而不是变量和函数。

英文:

You're passing the list of messages to send into send_mex, so it doesn't need to then reach out and modify list_of_message using its global name. It should only modify what's given to it. (Having it modify its parameter is also not great, but better than having it go change a global variable directly.)

That goes for the global sent-message queue, too; I'd just have it return the sent messages. The calling code can append them to the global if it ever calls send_mex more than once.

A for loop will break if you modify the list while you're looping over it, so don't do that either. If you're popping items off the list, just use a while that loops while the list has nonzero length:

def send_mex(to_send):
    sent = []
    while to_send:
        message = to_send.pop()
        print_it(message)
        sent.append(message)
    return sent


list_of_message = ['GO!!!', 'WAIT!!!', 'DAMN!!', 'OUCH!!!']
sent_message = send_mex(list_of_message)

If you append your final output code, you'll see that list_of_messages winds up empty, and the items that started out in it are now in sent_message.

You'll notice I uncapitalized the names; in standard Python coding style, initial capital letters are reserved for constants, not variables and functions.

答案2

得分: 1

你正在操作列表 List_of_messages:你既在迭代它,又从中弹出项目。这是你绝对应该避免的行为;它会产生意外的行为,就像你正在经历的那种情况一样。你迭代的同一个列表会发生变化,所以迭代周期会与你想象的不同。

我建议以下解决方案:

def print_message(message):
    print(message)

def send_messages(to_send, sent):
    to_send.reverse()
    while to_send:
        message = to_send.pop()
        print_message(message)
        sent.append(message)

messages = ['GO!!!', 'WAIT!!!', 'DAMN!!', 'OUCH!!!']
sent = []

send_messages(messages, sent)
print('要发送的消息列表:')
print_message(messages)
print('已发送的消息列表:')
print_message(sent)

在这里,你首先反转了列表(无论如何,它最终会被清空)。然后你使用一个 while 循环,在每次迭代中检查列表是否不为空(只有当 to_send 为空时,while 才会评估为布尔值 False)。然后你弹出消息(请记住列表已被反转),打印它,并将其附加到已发送的消息中。

英文:

You're messing with the list List_of_messages: you're both iterating on it and popping items from it. This is something you should definitely avoid; it generates unexpected behavior like the one you're experiencing. The same list on which you iterate gets changes, so that the iteration cycles come out different from what you imagined.

I suggest the following solution:

def print_message(message):
    print(message)

def send_messages(to_send, sent):
    to_send.reverse()
    while to_send:
        message = to_send.pop()
        print_message(message)
        sent.append(message)

messages = ['GO!!!', 'WAIT!!!', 'DAMN!!', 'OUCH!!!']
sent = []

send_messages(messages, sent)
print('List of messages to send:')
print_message(messages)
print('List of sent messages:')
print_message(sent)

Here you first reverse the list (which, in any case, will be emptied). Then you use a while cycle where at each iteration you check if the list is not empty (to_send will evaluate to a boolean False in the while only when it will be empty). Then you pop the message (remember that the list was reversed), you print it and you append it to the sent ones.

答案3

得分: 0

我看得出你是个初学者所以我会尽量让你多做一些工作

尝试运行这个脚本并试着理解它我只是添加了打印语句这样你可以看到`List_of_Message``Sended_message`的情况

我认为你已经理解了`pop()`会从列表中移除项目

但是,“传递给该方法的参数是可选的如果不传递默认索引-1会作为参数传递最后一项的索引)。”

所以如果你不传递参数它会移除列表的最后一项

如果你仍然有问题或者你不明白为什么你的for循环提前结束请随时回来我会编辑以添加更多信息
英文:

I can see you are a beginner, so I will try to make you work a little bit.

Try this script and try to understand it. I just added print so you can see what is going on with your List_of_Message and Sended_message.

def Print_It(message):
    print(message)


def Send_mex(To_send):
    for sende in To_send:
        Print_It(sende)
        print(f"Content of List_of_Message before pop : {List_of_Message}")
        current_message = List_of_Message.pop()
        print(f"Content of List_of_Message after pop : {List_of_Message}")
        print(f"Content of Sended_message before append : {Sended_message}")
        Sended_message.append(current_message)
        print(f"Content of Sended_message after append : {Sended_message}")

        print("\n\n")


List_of_Message = ["GO!!!", "WAIT!!!", "DAMN!!", "OUCH!!!"]
Sended_message = []

Send_mex(List_of_Message)
Print_It(List_of_Message)
Print_It(Sended_message)

I think you have understand that that pop() will remove the item from the list.

BUT

"The argument passed to the method is optional. If not passed, the default index -1 is passed as an argument (index of the last item)."

So if you don't give an argument, it will remove the last items of the list.

Feel free to reach back if you still have issue or you still don't understand why your for loop is finish early. I will edit to add more info if needed.

答案4

得分: 0

以下是您要翻译的代码部分:

尝试这个已编辑以满足您的期望输出
我们使用了两个循环!!!:

def Print_It(message):
    print(message)

def Send_mex(To_send):
    for sende in To_send:
        Print_It(sende)
    for sende in range(len(To_send)):
        Sended_message.append(List_of_Message.pop())

List_of_Message = ['GO!!!', 'WAIT!!!', 'DAMN!!', 'OUCH!!!']
Sended_message = []

Send_mex(List_of_Message)
Print_It(List_of_Message)
Print_It(Sended_message)

结果..

GO!!!
WAIT!!!
DAMN!!
OUCH!!!
[]
['OUCH!!!', 'DAMN!!', 'WAIT!!!', 'GO!!!']

请注意,我只提供了代码的翻译部分,不包括其他内容。

英文:

Try this (EDITED2MEET your desired output)
We use 2 for loops!!!:

def Print_It (message):
	print (message)
       
def Send_mex (To_send):
	for sende in To_send:
            Print_It(sende)
	for sende in range(len(To_send)):
		Sended_message.append(List_of_Message.pop())
		            
List_of_Message = ['GO!!!', 'WAIT!!!', 'DAMN!!', 'OUCH!!!']
Sended_message = []

Send_mex (List_of_Message)
Print_It (List_of_Message)
Print_It (Sended_message)

The result..:

GO!!!
WAIT!!!
DAMN!!
OUCH!!!
[]
['OUCH!!!', 'DAMN!!', 'WAIT!!!', 'GO!!!']

答案5

得分: -2

一般来说,如果在函数中传递了变量,并且你不希望修改函数外的这些变量,那么最好不要修改它们。在这种情况下,由于List_of_Message被传递为To_sendTo_sendList_of_Message 的浅拷贝,这意味着如果你修改List_of_MessageTo_send 也会被改变。

在这种情况下,由于你在迭代过程中修改了To_send,一个简单的解决方法是在循环开始时对其进行拷贝。

def Print_It(message):
    print(message)
       
def Send_mex(To_send):
    for sende in To_send.copy():
        Print_It(sende)
        current_message = List_of_Message.pop()
        Sended_message.append(current_message)

List_of_Message = ['GO!!!', 'WAIT!!!', 'DAMN!!', 'OUCH!!!']
Sended_message = []

Send_mex(List_of_Message)
Print_It(List_of_Message)
Print_It(Sended_message)
英文:

In general, you don't want to modify variables outside the function if they are also passed through the function. In this case, since List_of_Message is passed through as To_send, To_send is a shallow copy of List_of_Message, meaning if you modify List_of_Message, To_send is changed as well.

In this case, since you are modifying To_send as you are iterating over it, an easy fix would be to copy it at the start of the for loop.

def Print_It (message):
    print (message)
       
def Send_mex (To_send):
    for sende in To_send.copy():
        Print_It(sende)
        current_message = List_of_Message.pop()
        Sended_message.append(current_message)

List_of_Message = ['GO!!!', 'WAIT!!!', 'DAMN!!', 'OUCH!!!']
Sended_message = []

Send_mex (List_of_Message)
Print_It (List_of_Message)
Print_It (Sended_message)

huangapple
  • 本文由 发表于 2023年7月4日 23:11:59
  • 转载请务必保留本文链接:https://go.coder-hub.com/76613940.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定