在我的代码中,我必须询问用户一些输入。当满足条件时,程序应该停止运行!
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
和异常才能在执行过程中停止循环。否则,即使条件不再成立,当前迭代也将完成:
- 检查状况。它是
True
,所以开始第一次迭代 - 调用修改
ALIVE
的some_input
,因此该条件不再为真。然而,现在还不是检查情况的时候 - 运行循环的其他语句,如
print(stuff)
- 一旦循环中没有更多的代码(第一次迭代完成),请再次检查条件
- 它是
False
,所以停止循环
基本上,循环的执行方式与编写方式相同:
- 检查状况。如果
True
、goto 2
。否则跳过整个循环(goto 4
) - 开始执行循环体(循环中的代码)。
- 如果偶然发现
break
语句,请跳出当前循环:goto 4
- 如果出现异常,请中断我们正在做的一切,并传播异常,直到它在某个地方得到处理。如果未处理,则完全停止执行
- 如果偶然发现
- 一旦循环体被执行,
goto 1
- 循环后执行代码
在调用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()
但是,我强烈建议您不要使用这种方法。原因如下:
全局变量:使用全局变量会导致隐藏的副作用。对于较大的程序,很容易忘记可能正在使用和更改
ALIVE
变量的所有代码片段。从长远来看,过度使用全局变量将导致复杂性的增加。由于您已经定义了函数you_died
来专门处理停止while/loop
语句的过程,因此您可能希望通过为其定义alive
输入参数、将其更改为False
并返回其新值来最大限度地提高函数的优点。";是";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")