Is there a label/goto in Python?
Python中是否有
不,Python不支持标签和goto,如果这是您所追求的。它是一种(高度)结构化的编程语言。
Python为您提供了使用第一类函数执行goto所能完成的一些功能。例如:
1 2 3 4 5 6 7 8 9 10 11 12 | void somefunc(int a) { if (a == 1) goto label1; if (a == 2) goto label2; label1: ... label2: ... } |
可以像这样在python中完成:
1 2 3 4 5 6 7 8 9 10 | def func1(): ... def func2(): ... funcmap = {1 : func1, 2 : func2} def somefunc(a): funcmap[a]() #Ugly! But it works. |
当然,这不是替代goto的最佳方式。但是如果不确切地知道你要对goto做什么,很难给出具体的建议。
@ascobol:
最好的办法是将其包含在函数中或使用异常。对于功能:
1 2 3 4 5 | def loopfunc(): while 1: while 1: if condition: return |
对于例外:
1 2 3 4 5 6 | try: while 1: while 1: raise BreakoutException #Not a real exception, invent your own except BreakoutException: pass |
如果你来自另一种编程语言,使用异常来做这样的事情可能会有点尴尬。但我认为,如果您不喜欢使用异常,Python就不适合您。 :-)
我最近编写了一个函数装饰器,它在Python中启用
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 | from goto import with_goto @with_goto def range(start, stop): i = start result = [] label .begin if i == stop: goto .end result.append(i) i += 1 goto .begin label .end return result |
我不确定为什么人们会这样做。那就是说,我对此并不太认真。但是我想指出这种元编程在Python中是可行的,至少在CPython和PyPy中是这样,而且不仅像其他人那样滥用调试器API。你必须弄乱字节码。
我在官方的python设计和历史常见问题中找到了这个。
Why is there no goto?
You can use exceptions to provide a"structured goto" that even works
across function calls. Many feel that exceptions can conveniently
emulate all reasonable uses of the"go" or"goto" constructs of C,
Fortran, and other languages. For example:
1 2 3 4 5 6 7 8 9 | class label(Exception): pass # declare a label try: ... if condition: raise label() # goto label ... except label: # where to goto pass ... |
This doesn’t allow you to jump into the middle of a loop, but that’s
usually considered an abuse of goto anyway. Use sparingly.
在官方常见问题解答中甚至提到这一点非常好,并且提供了一个很好的解决方案示例。我真的很喜欢python,因为它的社区甚至像这样处理
要使用评论中的
1 2 3 4 5 6 7 | for i in range(5000): for j in range(3000): if should_terminate_the_loop: break else: continue # no break encountered break |
已经制作了一个工作版本:http://entrian.com/goto/。
注意:它是作为愚人节的笑话提供的。 (虽然工作)
1 2 3 4 5 6 7 8 9 10 11 12 | # Example 1: Breaking out from a deeply nested loop: from goto import goto, label for i in range(1, 10): for j in range(1, 20): for k in range(1, 30): print i, j, k if k == 3: goto .end label .end print"Finished " |
不用说。是的它有趣,但不要使用它。
通过一些工作向python添加'goto'之类的语句在技术上是可行的。我们将使用"dis"和"new"模块,这两个模块对于扫描和修改python字节代码都非常有用。
实现背后的主要思想是首先将代码块标记为使用"goto"和"label"语句。一个特殊的"@goto"装饰器将用于标记"goto"功能。然后,我们扫描这两个语句的代码,并对基础字节代码进行必要的修改。这一切都发生在源代码编译时。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 | import dis, new def goto(fn): """ A function decorator to add the goto command for a function. Specify labels like so: label .foo Goto labels like so: goto .foo Note: you can write a goto statement before the correspnding label statement """ labels = {} gotos = {} globalName = None index = 0 end = len(fn.func_code.co_code) i = 0 # scan through the byte codes to find the labels and gotos while i < end: op = ord(fn.func_code.co_code[i]) i += 1 name = dis.opname[op] if op > dis.HAVE_ARGUMENT: b1 = ord(fn.func_code.co_code[i]) b2 = ord(fn.func_code.co_code[i+1]) num = b2 * 256 + b1 if name == 'LOAD_GLOBAL': globalName = fn.func_code.co_names[num] index = i - 1 i += 2 continue if name == 'LOAD_ATTR': if globalName == 'label': labels[fn.func_code.co_names[num]] = index elif globalName == 'goto': gotos[fn.func_code.co_names[num]] = index name = None i += 2 # no-op the labels ilist = list(fn.func_code.co_code) for label,index in labels.items(): ilist[index:index+7] = [chr(dis.opmap['NOP'])]*7 # change gotos to jumps for label,index in gotos.items(): if label not in labels: raise Exception("Missing label: %s"%label) target = labels[label] + 7 # skip NOPs ilist[index] = chr(dis.opmap['JUMP_ABSOLUTE']) ilist[index + 1] = chr(target & 255) ilist[index + 2] = chr(target >> 8) # create new function from existing function c = fn.func_code newcode = new.code(c.co_argcount, c.co_nlocals, c.co_stacksize, c.co_flags, ''.join(ilist), c.co_consts, c.co_names, c.co_varnames, c.co_filename, c.co_name, c.co_firstlineno, c.co_lnotab) newfn = new.function(newcode,fn.func_globals) return newfn if __name__ == '__main__': @goto def test1(): print 'Hello' goto .the_end print 'world' label .the_end print 'the end' test1() |
希望这能回答这个问题。
您可以使用用户定义的例外来模拟
例:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 | class goto1(Exception): pass class goto2(Exception): pass class goto3(Exception): pass def loop(): print 'start' num = input() try: if num<=0: raise goto1 elif num<=2: raise goto2 elif num<=4: raise goto3 elif num<=6: raise goto1 else: print 'end' return 0 except goto1 as e: print 'goto1' loop() except goto2 as e: print 'goto2' loop() except goto3 as e: print 'goto3' loop() |
我正在寻找类似的东西
1 2 3 4 5 6 7 8 | for a in xrange(1,10): A_LOOP for b in xrange(1,5): for c in xrange(1,5): for d in xrange(1,5): # do some stuff if(condition(e)): goto B_LOOP; |
所以我的方法是使用布尔值来帮助从嵌套的for循环中脱离出来:
1 2 3 4 5 6 7 8 9 10 11 | for a in xrange(1,10): get_out = False for b in xrange(1,5): if(get_out): break for c in xrange(1,5): if(get_out): break for d in xrange(1,5): # do some stuff if(condition(e)): get_out = True break |
现在有。去
我认为这可能对您正在寻找的内容有用。
我有自己的做事方式。
我使用单独的python脚本。
如果我想循环:
file1.py
1 2 3 | print("test test") execfile("file2.py") a = a + 1 |
file2.py
1 2 3 4 5 | print(a) if a == 10: execfile("file3.py") else: execfile("file1.py") |
file3.py
1 | print(a +" equals 10") |
(注意:此技术仅适用于Python 2.x版本)
我想要相同的答案,我不想使用
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 | def sample(): print"This room is full of gold how much do you want?" choice = raw_input(">") how_much = int(choice) if"0" in choice or"1" in choice: check(how_much) else: print"Enter a number with 0 or 1" sample() def check(n): if n < 150: print"You are not greedy, you win" exit(0) else: print"You are nuts!" exit(0) |
Python 2和3
1 | pip3 install goto-statement |
Tested on Python 2.6 through 3.6 and PyPy.
链接:goto语句
foo.py
1 2 3 4 5 6 7 8 9 10 | from goto import with_goto @with_goto def bar(start, stop): label .bar_begin ... goto .bar_begin |
对于转发Goto,您可以添加:
1 2 3 4 5 6 | while True: if some condition: break #... extra code break # force code to exit. Needed at end of while loop #... continues here |
这只会对简单的场景有所帮助(即嵌套这些会让你陷入混乱)
代替python goto等价物,我使用以下方式的break语句来快速测试我的代码。 这假设您有结构化代码库。 测试变量在函数开始时初始化,我只是将"If test:break"块移动到我想测试的嵌套if-then块或循环的末尾,修改代码末尾的返回变量 反映我正在测试的块或循环变量。
1 2 3 4 5 6 7 | def x: test = True If y: # some code If test: break return something |
没有另一种方法来实现goto语句
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 | class id: def data1(self): name=[] age=[] n=1 while n>0: print("1. for enter data") print("2. update list") print("3. show data") print("choose what you want to do ?") ch=int(input("enter your choice")) if ch==1: n=int(input("how many elemet you want to enter=")) for i in range(n): name.append(input("NAME")) age.append(int(input("age"))) elif ch==2: name.append(input("NAME")) age.append(int(input("age"))) elif ch==3: try: if name==None: print("empty list") else: print("name \t age") for i in range(n): print(name[i]," \t",age[i]) break except: print("list is empty") print("do want to continue y or n") ch1=input() if ch1=="y": n=n+1 else: print("name \t age") for i in range(n): print(name[i]," \t",age[i]) n=-1 p1=id() p1.data1() |