虽然循环即使在变量更改后也不会停止循环



在我的代码中,我必须询问用户一些输入。当满足条件时,程序应该停止运行!

ALIVE = True
def you_died():
global ALIVE
ALIVE = False
def some_input():
choice = input()
if choice == "yes":
you_died()
while ALIVE is True:
some_input()
print("some string")

为什么我的代码仍在打印";一些字符串";即使变量ALIVE为False?

如何从函数内部打破循环?

虽然每次迭代对条件求值一次,但更改条件中使用的变量不会导致它立即中断。此外,您不能从函数中break。但是你可以在调用你的函数后测试你的全局,如果它不是真的,在执行while循环中的任何其他步骤之前中断:

ALIVE = True
def you_died():
global ALIVE
ALIVE = False
def some_input():
choice = input()
if choice == "yes":
you_died()
while ALIVE is True:
some_input()
if not ALIVE: break
print("some string")

只有break和异常才能在执行过程中停止循环。否则,即使条件不再成立,当前迭代也将完成:

  1. 检查状况。它是True,所以开始第一次迭代
  2. 调用修改ALIVEsome_input,因此该条件不再为真。然而,现在还不是检查情况的时候
  3. 运行循环的其他语句,如print(stuff)
  4. 一旦循环中没有更多的代码(第一次迭代完成),请再次检查条件
  5. 它是False,所以停止循环

基本上,循环的执行方式与编写方式相同:

  1. 检查状况。如果Truegoto 2。否则跳过整个循环(goto 4)
  2. 开始执行循环体(循环中的代码)。
    1. 如果偶然发现break语句,请跳出当前循环:goto 4
    2. 如果出现异常,请中断我们正在做的一切,并传播异常,直到它在某个地方得到处理。如果未处理,则完全停止执行
  3. 一旦循环体被执行,goto 1
  4. 循环后执行代码

在调用some_input()之后,在循环重新启动和检查ALIVE之前,打印"some string",因此循环没有机会决定在调用some_input()和执行print之间不重复。

一个简单的修复方法是在循环开始前调用some_input()一次,以便用第一次some_input()调用的结果初始化ALIVE,然后在循环结束时(而不是开始时)调用some_input(),以便在再次打印之前重新评估ALIVE

some_input()
while ALIVE:  # no need to say "is True"
print("some string")
some_input()

组织这个代码的一个更好的方法是让你的函数告诉你你是否死了(通过它的返回值,而不是global),如果死了,break立即循环。这允许你使用一个简单的while True,依靠break在适当的时候停止循环:

def you_died():
"""Asks for input, returns True if you died."""
return input() == "yes"
while True:
if you_died():
break
print("some string")

ALIVE变量更改为False,只会停止执行新迭代的while语句。

如果希望print("some string")语句仅在用户回答除";是";,只要对当前实现进行最小的更改,就可以将print移动到some_input,如下所示:


ALIVE = True
def you_died():
global ALIVE
ALIVE = False
def some_input():
choice = input()
if choice == "yes":
you_died()
else:
print("some string")

while ALIVE is True:
some_input()

但是,我强烈建议您不要使用这种方法。原因如下:

  1. 全局变量:使用全局变量会导致隐藏的副作用。对于较大的程序,很容易忘记可能正在使用和更改ALIVE变量的所有代码片段。从长远来看,过度使用全局变量将导致复杂性的增加。由于您已经定义了函数you_died来专门处理停止while/loop语句的过程,因此您可能希望通过为其定义alive输入参数、将其更改为False并返回其新值来最大限度地提高函数的优点。

  2. ";是";vs";是":您希望您的程序在用户回答"时停止while语句吗;是";,或";如果"是"是";,甚至";是的"?如果是这样的话,也许将if choice == "yes":...更改为类似if "yes" in choice.lower():...的方法可能更稳健。

考虑到上述两点,这里有一个关于如何重写代码的建议:


def some_input(case_insensitive: bool = True) -> bool:
"""Ask User for input, and return `True` if they answer something other than "yes".
Parameters
----------
case_insensitive: bool, default = True
Whether to consider User's input case-sensitive or not, when checking
looking for replies equal to "yes". For example, if `case_insensitive` is set to
`True`, then the function considers "yes", "Yes", and "YES" as the same
answer.

Returns
-------
bool
`True`, if User inputs anything that doesn't contain the word "yes".
"""
choice = input()
if case_insensitive:
choice = choice.lower()
return "yes" not in choice

# Only enters the while statement, if the user
# answers something other than "yes" (e.g., "no") 
while some_input():
print("some string")

最新更新