Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/python-3.x/19.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
如何在python中检测无限循环_Python_Python 3.x_Infinite Loop - Fatal编程技术网

如何在python中检测无限循环

如何在python中检测无限循环,python,python-3.x,infinite-loop,Python,Python 3.x,Infinite Loop,我正在学习Python3,正在做一个练习,要求编写一个Python程序,模拟/读取一个基本程序作为输入。我一直在写Python程序中应该检测无限循环的部分。以下是我目前掌握的代码: def execute(prog): while True: location = 0 if prog[location] == len(prog) - 1: break return "success" getT = prog[locat

我正在学习Python3,正在做一个练习,要求编写一个Python程序,模拟/读取一个基本程序作为输入。我一直在写Python程序中应该检测无限循环的部分。以下是我目前掌握的代码:

def execute(prog):
   while True:
      location = 0
      if prog[location] == len(prog) - 1:
         break
         return "success"
      getT = prog[location].split()
      T = len(getT) - 1
      location = findLine(prog, T)
   visited = [False] * len(prog)
这里,prog是包含基本程序的字符串列表(字符串的形式为5 GOTO 30、10 GOTO 20等)

T是prog[location]中指示的目标字符串

如果BASIC程序有一个无限循环,那么我的Python程序将有一个无限循环。我知道,如果任何一行被访问两次,那么它将永远循环,我的程序将返回“无限循环”

教程助手给出的提示是“初始化访问的列表=[False]*len(prog)并在访问prog[i]时将访问的[i]更改为True。每次通过循环,访问的[]中都会更新一个值。想想如何更改列表中的单个值。然后想想如何确定访问的[]中需要更改的值。”


这就是我一直坚持的部分。如何跟踪prog中哪些字符串已被访问/循环

我不确定我是否同意两次访问一条线就证明了一个无限循环。见问题下的评论。但我可以回答实际问题

以下是提示:

教程助手给出的提示是“初始化访问的列表=[False]*len(prog)并在访问prog[i]时将访问的[i]更改为True。每次通过循环,访问的[]中都会更新一个值。想想如何更改列表中的单个值。然后想想如何确定访问的[]中需要更改的值。”

这意味着您应该有两个列表,一个包含程序,另一个包含真/假标志。第二个将命名为
已访问
,最初包含
False

Python代码如提示所示:

visited = [False] * len(prog)
这将使用
*
列表运算符“列表重复”,重复长度为1的列表,并生成长度更长的新列表

要将访问的[i]更改为
True
很简单:

visited[i] = True
然后你可以这样做:

if visited[i]:
    print("We have already visited line {}".format(i))
    print("Infinite loop?  Exiting.")
    sys.exit(1)
class ProgramCode(object):
    def __init__(self, statement):
        self.code = statement
        self.visited = False

prog = []
with open(input_basic_program_file, "rt") as f:
    for line in f:
        prog.append(ProgramCode(line))
请注意,我们在测试
True
值时,只需说
如果访问[i]:

如果访问[i]==True:,我们也可以编写
,但是较短的形式就足够了,并且是Python社区的习惯。这里记录了这一习惯用语和其他习惯用语:

对于一个如此小的程序,像这样保存两个列表并不太糟糕。对于较大且复杂的程序,我更喜欢将所有内容放在一个地方。这将使用一个你可能还没有学会的“类”。大概是这样的:

if visited[i]:
    print("We have already visited line {}".format(i))
    print("Infinite loop?  Exiting.")
    sys.exit(1)
class ProgramCode(object):
    def __init__(self, statement):
        self.code = statement
        self.visited = False

prog = []
with open(input_basic_program_file, "rt") as f:
    for line in f:
        prog.append(ProgramCode(line))
现在,我们没有两个列表,而是一个列表,其中每个项目都是一些基本代码和一个
已访问的
标志

另外,上面显示了一个显式的
for
循环,该循环重复使用
.append()
添加到列表中。一个有经验的Python开发人员可能会使用“列表理解”来代替,但我想让它尽可能容易理解

这是清单。如果现在看起来很奇怪,不要担心;你的班级最终会教你这个

with open(input_basic_program_file, "rt") as f:
    prog = [ProgramCode(line) for line in f]

我知道Python中没有自动检测无限循环的方法,但是通过使用分治方法和测试单个函数,您可以找到有问题的函数或代码块,然后继续调试

如果Python程序输出数据,但您从未看到该输出,那么这就很好地表明您有一个无限循环。您可以在repl中测试所有函数,而不“返回”[命令提示符]的函数可能是可疑的

您可以在某种调试变量下写入输出,以便在一切正常时关闭。这可能是Python类的一个成员变量,您的代码必须随时访问该类,或者您可以使用一个模块范围的变量,如
Debug=1
,并使用调试级别打印不同数量的调试信息,如1多一点、2多一点、3多一点、4多一点


例如,如果在可疑函数中打印循环计数器的值,那么最终该循环计数器将继续打印远远超过数据计数(测试记录)您曾经使用过测试。

我用J.Carlos p.的部分答案和steveha给出的提示,以及使用说明给出的提示,想出了一个组合:

def execute(prog):
   location = 0
   visited = [False] * len(prog)
   while True:
      if location==len(prog)-1: 
         return "success" 
      findT = prog[location].split()
      T = findT[- 1]
      if visited[location]:
         return "infinite loop"
      visited[location] = True
      location = findLine(prog, T)

从技术上讲,不可能确定程序是否有无限循环。看。
如果任何一行被访问两次,那么它就会永远循环,这不是真的。如果这是真的,那么任何循环都会变成无限循环。@DavidRobinson从我嘴里说出了这些话。这很好地回答了这个问题。如果他的BASIC版本足够小(比如说,no-If,only-PRINT-and-GOTO等等),那么它就和他说的一模一样——如果一行被访问两次,它就是一个无限循环。因为这是一项作业,类似的情况也会发生。@RemcoGerlich如果是这样的话,问题应该相应地重新表述。他已经说过“我知道,如果任何一行被访问两次,那么它就会永远循环”,显然他的辅导助理不仅证实了这一点,而且给了他建议。所以我想我们可以把这句话当作是给定的——他需要检测一行是否被访问了两次。是的,除非我把
访问过的
作为一个集合,如果我访问过
就写
。它仍然是O(1)查找,但它使用的内存与访问的行数成比例,而不是程序中的行数。嗯,我认为程序最好遵循TA的提示。