在Python中是否有goto或任何等价的东西能够跳转到特定的代码行?
当前回答
我在官方的python设计和历史FAQ中找到了这个。
为什么没有goto? 您可以使用异常来提供一个甚至可以工作的“结构化goto” 跨函数调用。许多人认为异常可以方便地实现 模拟C语言中“go”或“goto”结构的所有合理使用, Fortran和其他语言。例如:
class label(Exception): pass # declare a label
try:
...
if condition: raise label() # goto label
...
except label: # where to goto
pass
...
这并不允许你跳到循环的中间,但那是 通常被认为是对goto的滥用。很少使用。
在官方常见问题解答中甚至提到了这一点,并且提供了一个很好的解决方案示例,这非常好。我真的很喜欢python,因为它的社区甚至是这样对待goto的;)
其他回答
在执行“goto”时,首先必须问“goto”是什么。虽然看起来很明显,但大多数人都没有考虑goto与函数栈之间的关系。
如果在函数内部执行“goto”,实际上就放弃了函数调用堆栈。这被认为是一种糟糕的做法,因为函数栈的设计期望在委托一个中间任务之后,您将继续您离开的地方。这就是为什么goto用于异常,而异常可以用来模拟goto,我将对此进行解释。
Finite state machines are probably the best use case for goto, which most of the time are implemented in a kludgy way with loops and switch statements, but I believe that "top level" gotos, are the cleanest, most semantic way to implement finite state machines. In this case, you want to make sure, if you have more variables, they are globals, and don't require encapsulation. Make sure you first model your variable state space(which may be different from execution state, ie the finite state machine).
我相信有合理的设计理由使用goto,异常处理是特殊情况下,混合goto和函数是有意义的。然而,在大多数情况下,您希望将自己限制在“顶级”goto,因此永远不要在函数中调用goto,而只在全局作用域中调用。
在现代语言中模拟顶级goto最简单的方法是实现顶级goto只需要全局变量和空调用堆栈。因此,为了保持调用堆栈为空,每当调用新函数时都返回。下面是一个输出前n个斐波那契数的例子:
a = 0
b = 1
n = 100
def A():
global a, b
a = a + b
n -= 1
print(a)
return B() if n > 0 else 0
def B():
global a, b
b = a + b
n -= 1
print(b)
return A() if n > 0 else 0
A()
虽然这个示例可能比循环实现更详细,但它也更强大和灵活,并且不需要特殊情况。它让你有一个完整的有限状态机。您还可以使用goto运行器对此进行修改。
def goto(target):
while(target) target = target()
def A():
global a, b
a = a + b
print(a)
return B
def B():
global a, b
b = a + b
print(b)
return A
goto(A)
为了强制执行“返回”部分,您可以编写一个goto函数,在完成时抛出一个异常。
def goto(target):
target()
throw ArgumentError("goto finished.")
def A():
global a, b
a = a + b
print(a)
goto(B)
def B()
global a, b
b = a + b
print(b)
goto(A)
goto(A)
因此,您可以看到,这在很大程度上是过度思考的,而调用一个函数然后抛出一个错误的helper函数就是您所需要的。您可以将它进一步包装在一个“start”函数中,这样错误就会被捕获,但我认为这并不是严格必要的。虽然其中一些实现可能会耗尽调用堆栈,但第一个运行器示例将其保持为空,如果编译器可以进行尾部调用优化,这也会有所帮助。
虽然在Python中没有任何等同于goto/label的代码,但您仍然可以使用循环来获得goto/label的这种功能。
让我们以下面所示的代码示例为例,其中goto/label可以在python以外的任意语言中使用。
String str1 = 'BACK'
label1:
print('Hello, this program contains goto code\n')
print('Now type BACK if you want the program to go back to the above line of code. Or press the ENTER key if you want the program to continue with further lines of code')
str1 = input()
if str1 == 'BACK'
{
GoTo label1
}
print('Program will continue\nBla bla bla...\nBla bla bla...\nBla bla bla...')
现在,通过使用下面所示的while循环,可以在python中实现上述代码示例的相同功能。
str1 = 'BACK'
while str1 == 'BACK':
print('Hello, this is a python program containing python equivalent code for goto code\n')
print('Now type BACK if you want the program to go back to the above line of code. Or press the ENTER key if you want the program to continue with further lines of code')
str1 = input()
print('Program will continue\nBla bla bla...\nBla bla bla...\nBla bla bla...')
我最近写了一个函数装饰器,在Python中启用goto,就像这样:
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。不过,您必须修改字节码。
我认为while循环是“goto_Statement”的替代。因为3.6之后,goto循环不再工作了。我还写了一个while循环的例子。
str1 = "stop"
while str1 == "back":
var1 = int(input(" Enter Ist Number: "))
var2 = int(input(" Enter 2nd Number: "))
var3 = print(""" What is your next operation
For Addition Press And Enter : 'A'
For Muliplt Press And Enter : 'M'
For Division Press And Enter : 'D'
For Subtaction Press And Enter : 'S' """)
var4 = str(input("For operation press any number : "))
if(var1 == 45) and (var2 == 3):
print("555")
elif(var1 == 56) and (var2 == 9):
print("77")
elif(var1 == 56) and (var2 == 6):
print("4")
else:
if(var4 == "A" or "a"):
print(var1 + var2)
if(var4 == "M" or "m"):
print(var1 * var2)
if(var4 == "D" or "d"):
print(var1 / var2)
if(var4 == "S" or "s"):
print(var1 - var2)
print("if you want to continue then type 'stop'")
str1 = input()
print("Strt again")
使用评论中@bobince的建议来回答@ascobol的问题:
for i in range(5000):
for j in range(3000):
if should_terminate_the_loop:
break
else:
continue # no break encountered
break
else块的缩进是正确的。代码在循环Python语法后使用模糊的else。参见为什么python在for和while循环之后使用'else' ?
推荐文章
- Numpy Max vs amax vs maximum
- 我应该在.gitignore文件中添加Django迁移文件吗?
- 每n行有熊猫
- 实例属性attribute_name定义在__init__之外
- 如何获取在Python中捕获的异常的名称?
- 第一次出现的值大于现有值的Numpy
- 如何从Python函数中返回两个值?
- 前一个月的Python日期
- Python中方括号括起来的列表和圆括号括起来的列表有什么区别?
- Python日志记录不输出任何东西
- 每n秒运行特定代码
- SQLAlchemy是否有与Django的get_or_create等价的函数?
- 如何将python datetime转换为字符串,具有可读格式的日期?
- 美丽的汤和提取div及其内容的ID
- 在Python中重置生成器对象