The equivalent of a GOTO in python
Goto
s are universally reviled in computer science and programming as they lead to very unstructured code.
Python (like almost every programming language today) supports structured programming which controls flow using if/then/else, loop and subroutines.
The key to thinking in a structured way is to understand how and why you are branching on code.
For example, lets pretend Python had a goto
and corresponding label
statement shudder. Look at the following code. In it if a number is greater than or equal to 0 we print if it
number = input()
if number < 0: goto negative
if number % 2 == 0:
print "even"
else:
print "odd"
goto end
label: negative
print "negative"
label: end
print "all done"
If we want to know when a piece of code is executed, we need to carefully traceback in the program, and examine how a label was arrived at - which is something that can't really be done.
For example, we can rewrite the above as:
number = input()
goto check
label: negative
print "negative"
goto end
label: check
if number < 0: goto negative
if number % 2 == 0:
print "even"
else:
print "odd"
goto end
label: end
print "all done"
Here, there are two possible ways to arrive at the "end", and we can't know which one was chosen. As programs get large this kind of problem gets worse and results in spaghetti code
In comparison, below is how you would write this program in Python:
number = input()
if number >= 0:
if number % 2 == 0:
print "even"
else:
print "odd"
else:
print "negative"
print "all done"
I can look at a particular line of code, and know under what conditions it is met by tracing back the tree of if/then/else
blocks it is in. For example, I know that the line print "odd"
will be run when a ((number >= 0) == True) and ((number % 2 == 0) == False)
.
Alternative to Goto, Label in Python?
There are lots of ways to do this, but generally you'll want to use loops, and you may want to explore break
and continue
. Here's one possible solution:
import random
x = random.randint(1, 100)
prompt = "Guess the number between 1 and 100: "
while True:
try:
y = int(raw_input(prompt))
except ValueError:
print "Please enter an integer."
continue
if y > x:
prompt = "Wrong! Try a LOWER number: "
elif y < x:
prompt = "Wrong! Try a HIGHER number: "
else:
print "Correct!"
break
continue
jumps to the next iteration of the loop, and break
terminates the loop altogether.
(Also note that I wrapped int(raw_input(...))
in a try/except to handle the case where the user didn't enter an integer. In your code, not entering an integer would just result in an exception. I changed the 0 to a 1 in the randint
call too, since based on the text you're printing, you intended to pick between 1 and 100, not 0 and 100.)
`goto` in Python
I know what everybody is thinking:
However, there might be some didactic cases where you actually need a goto
.
This python recipe provides the goto
command as a function decorator.
The goto decorator (Python recipe by Carl Cerecke)
This is the recipe for you if you are sick of the slow speed of the
existinggoto
module http://entrian.com/goto/. Thegoto
in this
recipe is about 60x faster and is also cleaner (abusingsys.settrace
seems hardly pythonic). Because this is a decorator, it alerts the
reader which functions usegoto
. It does not implement the comefrom
command, although it is not difficult to extend it to do so (exercise
for the reader). Also, computed gotos aren't supported; they're not
pythonic.
- Use
dis.dis(fn)
to show the bytecode disassembly of a function.- The bytecodes of a function are accessed by
fn.func_code.co_code
.
This is readonly so:- The decorated function is created exactly the same as the old one,
but with the bytecode updated to obey thegoto
commands.- This is 2.x only; the new module is not in python 3.x (another
exercise for the reader!)
Usage
@goto
def test1(n):
s = 0
label .myLoop
if n <= 0:
return s
s += n
n -= 1
goto .myLoop
>>> test1(10)
55
Update
Here're two additional implementations compatible with Python 3:
- https://github.com/cdjc/goto
- https://github.com/snoack/python-goto
Goto statement in python - what other way is there?
You should give us the code, or at least an example showing what the structure really is.
Maybe you could do so:
take screenshot
condition = (condition a) and (condition b) and ... and (condition z)
while (not condition):
take screenshot
condition = (condition a) and (condition b) and ... and (condition z)
how to work around go-to in python?
In this particular case, wrapping the whole thing in a while True
will achieve the same behavior:
while True:
while (cond1):
print("inside cond1")
Function1(x,y,z)
else:
if (object.exists("obj1")):
Screen1 = waitForObject("obj1")
print ("Inside Screen1")
while (Screen1.visible):
Function1(a,b,c)
else:
break
Checking this branch-by-branch:
If cond1 is met, we continually execute Function1(x, y, z)
Once cond1 is not met, we fall into else.
If obj1 exists, we wait for obj1, otherwise, we break out of the while True loop.
After waiting for obj1, we continue to run Function1(a,b,c) while Screen1 is visible, and then go back to the beginning of the while True loop (consistent with the original goto).
Related Topics
How to Convert String to Binary
How to Read Text from the Clipboard
Pandas: Multiple Conditions While Indexing Data Frame - Unexpected Behavior
Difference Between Class and Instance Methods
Finding All Possible Permutations of a Given String in Python
Split Cell into Multiple Rows in Pandas Dataframe
How to Handle the Window Close Event in Tkinter
Rank Items in an Array Using Python/Numpy, Without Sorting Array Twice
How to Create a Copy of an Object in Python
Find Common Substring Between Two Strings
Can You Monkey Patch Methods on Core Types in Python
Why Does (1 in [1,0] == True) Evaluate to False
What Does 'Weight' Do in Tkinter
How to Extract Multiple JSON Objects from One File
How to Turn a Python Datetime into a String, with Readable Format Date
Groupby Results to Dictionary of Lists
Can Not Click on a Element: Elementclickinterceptedexception in Splinter/Selenium