Good python equivalent to C goto

K

Kurien Mathew

Hello,

Any suggestions on a good python equivalent for the following C code:

while (loopCondition)
{
if (condition1)
goto next;
if (condition2)
goto next;
if (condition3)
goto next;
stmt1;
stmt2;
next:
stmt3;
stmt4;
}



Thanks
Kurien
 
T

Thomas Mlynarczyk

Kurien said:
Any suggestions on a good python equivalent for the following C code:

while (loopCondition)
{
if (condition1)
goto next;
if (condition2)
goto next;
if (condition3)
goto next;
stmt1;
stmt2;
next:
stmt3;
stmt4;
}

while loopCondition:
if not( cond1 or cond2 or cond3 ):
stmt1
stmt2
stmt3
stmt4

Not tested.
Greetings,
Thomas
 
F

Fredrik Lundh

Kurien said:
Any suggestions on a good python equivalent for the following C code:

while (loopCondition)
{
if (condition1)
goto next;
if (condition2)
goto next;
if (condition3)
goto next;
stmt1;
stmt2;
next:
stmt3;
stmt4;
}

seems as if you *don't* want to execute the first part if any of the
conditions are true. in other words,

while loopCondition:
if not (condition1 or condition2 or condition3):
stmt1
stmt2
stmt3
stmt4

</F>
 
C

Christian Heimes

Kurien said:
Hello,

Any suggestions on a good python equivalent for the following C code:

There are various ways to write your example in Python. For example

while loopCondition:
condition = 1
while condition:
if condition1:
break
if condition2:
break
if condition3:
break
stmt1
stmt2
condition = 0
else:
stmt3
stmt4

The else block of while isn't execute if you break out of while.

You can emulate multiple gotos with exceptions. In general you shouldn't
try to mimic C in Python code. C like Python code is often hard to read
and slower than well designed Python code.
 
M

Michael Torrie

Dennis said:
Nasty code even for C... I've never used goto in C... Options:
convert the statements of next into a function, and put in an else
clause...

I think the parent post's pseudocode example was too simple to show the
real benefits and use cases of goto in C. Obviously his simple example
was contrived and could easily be solved with proper if tests. Your
idea of using a function is correct for python, though, but not for C

However, what you say about else clauses gets extremely hairy when you
have to deal with multiple nested if statements. The most common use
case in C for goto is when you have cleanup code that must run before
leaving a function. Since any number of things could happen while
processing a function (at any level of the if statement) that would
trigger an exit, having a whole bunch of else statements gets very, very
tedious and messy. Often involves a lot of code duplication too. Goto
is direct and much cleaner and more readable.

A function in C wouldn't work for this because of scoping rules.

However it's not necessary in python to do any of this, since you can
define nested functions that have access to the parent scope. Anytime
you need to clean up, just call the nested cleanup function and then return.
 
M

Michael Torrie

Kurien said:
Hello,

Any suggestions on a good python equivalent for the following C code:

while (loopCondition)
{
if (condition1)
goto next;
if (condition2)
goto next;
if (condition3)
goto next;
stmt1;
stmt2;
next:
stmt3;
stmt4;
}

I think the most direct translation would be this:

def whateverfunc():

def next_func():
stmt3
stmt4

while loopCondition:
if condition1:
next_func()
return
if condition2:
next_func()
return
if condition3:
next_func()
return
stmt1
stmt2
 
M

Michael Torrie

Michael said:
I think the most direct translation would be this:

Nevermind I forgot about the while loop and continuing on after it.
Guess the function doesn't quite fit this use case after all.
 
C

Carl Banks

However it's not necessary in python to do any of this, since you can
define nested functions that have access to the parent scope.  Anytime
you need to clean up, just call the nested cleanup function and then return.

That is unnecessary and dangerous in Python.

98% of the time the Python interpreter cleans up what you would have
had to clean up by hand in C.

The rest of the time you should be using a try...finally block to
guarantee cleanup, or a with block to get the interpreter do it for
you.

Calling a nested function to perform cleanup is prone to omission
errors, and it doesn't guarantee that cleanup will happen if an
exception is raised.


Carl Banks
 
I

info

as an oldtimer, I know that in complex code the goto statement is
still the easiest to code and understand.

I propose this solution using exception.

The string exception is deprecated but is simpler for this example.



# DeprecationWarning: raising a string exception is deprecated

def Goto_is_not_dead(nIn):
try:
if (nIn == 1): raise 'Goto_Exit'
if (nIn == 2): raise 'Goto_Exit'

print 'Good Input ' + str(nIn)
raise 'Goto_Exit'

except 'Goto_Exit':
print 'any input ' + str(nIn)

if __name__ == '__main__':
Goto_is_not_dead(2)
Goto_is_not_dead(3)
 
M

Marc 'BlackJack' Rintsch

Any suggestions on a good python equivalent for the following C code:

while (loopCondition)
{
if (condition1)
goto next;
if (condition2)
goto next;
if (condition3)
goto next;
stmt1;
stmt2;
next:
stmt3;
stmt4;
}

(Don't) use the `goto` module: http://entrian.com/goto/ :)

from goto import goto, label

# ...

while loop_condition:
if condition1 or condition2 or condition3:
goto .next
print 'stmt1'
print 'stmt2'
label .next
print 'stmt3'
print 'stmt4'


Ciao,
Marc 'BlackJack' Rintsch
 
M

Matthew Fitzgibbons

Kurien said:
Hello,

Any suggestions on a good python equivalent for the following C code:

while (loopCondition)
{
if (condition1)
goto next;
if (condition2)
goto next;
if (condition3)
goto next;
stmt1;
stmt2;
next:
stmt3;
stmt4;
}



Thanks
Kurien

I would not be too happy if I saw C code like that in my repository.
This is equivalent:

while (loopCondition) {
if (!(condition1 || condition2 || condition3)) {
stmt1;
stmt2;
}
stmt3;
stmt4;
}


In Python:

while (loopCondition):
if not (condition1 or condition2 or condition3):
stmt1
stmt2
stmt3
stmt4

If stmt3 and stmt4 are error cleanup code, I would use try/finally.

while loopCondition:
try:
if condition1:
raise Error1()
if condition2:
raise Error2()
if condition3:
raise Error3()
stmt1
stmt2
finally:
stmt3
stmt4

This will also bail out of the loop on and exception and the exception
will get to the next level. If you don't want that to happen, put an
appropriate except block before the finally.

-Matt
 
I

info

I would not be too happy if I saw C code like that in my repository.
This is equivalent:

while (loopCondition) {
     if (!(condition1 || condition2 || condition3)) {
         stmt1;
         stmt2;
     }
     stmt3;
     stmt4;

}

In Python:

while (loopCondition):
     if not (condition1 or condition2 or condition3):
         stmt1
         stmt2
     stmt3
     stmt4

If stmt3 and stmt4 are error cleanup code, I would use try/finally.

while loopCondition:
     try:
         if condition1:
             raise Error1()
         if condition2:
             raise Error2()
         if condition3:
             raise Error3()
         stmt1
         stmt2
     finally:
         stmt3
         stmt4

This will also bail out of the loop on and exception and the exception
will get to the next level. If you don't want that to happen, put an
appropriate except block before the finally.

-Matt- Hide quoted text -

- Show quoted text -

class Goto_Target(Exception):
pass

def Goto_is_not_dead(nIn):
try:
if (nIn == 1): raise Goto_Target
if (nIn == 2): raise Goto_Target

inv = 1.0 / nIn
print 'Good Input ' + str(nIn) + ' inv=' + str(inv)

except Goto_Target:
pass
except Exception, e:
print 'Error Input ' + str(nIn) + ' ' + str(e)
finally:
print 'any input ' + str(nIn)

if __name__ == '__main__':
Goto_is_not_dead(0)
Goto_is_not_dead(2)
Goto_is_not_dead(3)
 
M

Matthew Fitzgibbons

class Goto_Target(Exception):
pass

def Goto_is_not_dead(nIn):
try:
if (nIn == 1): raise Goto_Target
if (nIn == 2): raise Goto_Target

inv = 1.0 / nIn
print 'Good Input ' + str(nIn) + ' inv=' + str(inv)

except Goto_Target:
pass
except Exception, e:
print 'Error Input ' + str(nIn) + ' ' + str(e)
finally:
print 'any input ' + str(nIn)

if __name__ == '__main__':
Goto_is_not_dead(0)
Goto_is_not_dead(2)
Goto_is_not_dead(3)

I think this is needlessly ugly. You can accomplish the same with a
simple if-else. In this case you're also masking exceptions other than
Goto_Target, which makes debugging _really_ difficult. If you need to
have the cleanup code executed on _any_ exception, you can still use
try-finally without any except blocks. Your code is equivalent to this:

def goto_is_dead(n):
try:
if n == 0 or n == 1 or n == 2:
# if you're validating input, validate the input
print "Error Input %s" % n
else:
print "Good Input %s inv= %s" % (n, (1. / n))
finally:
print "any input %s" % n

if __name__ == '__main__':
goto_id_dead(0)
goto_id_dead(2)
goto_id_dead(3)

More concise, readable, and maintainable.

-Matt
 
P

Paul Hankin

Hello,

Any suggestions on a good python equivalent for the following C code:

while (loopCondition)
{
        if (condition1)
                goto next;
        if (condition2)
                goto next;
        if (condition3)
                goto next;
        stmt1;
        stmt2;
next:
        stmt3;
        stmt4;
  }

Extract complex test as a function. Assuming conditions 1, 2 and 3 are
difficult enough not to put them all one one line, put them in a
function which describes what they're testing.

def should_do_12(args):
if condition1:
return False
if condition2:
return False
if condition3:
return False
return True

while loop_condition:
if should_do_12(args):
stmt1
stmt2
stmt3
stmt4

This is probably the right way to write it in C too.
 
I

info

I think this is needlessly ugly. You can accomplish the same with a
simple if-else. In this case you're also masking exceptions other than
Goto_Target, which makes debugging _really_ difficult. If you need to
have the cleanup code executed on _any_ exception, you can still use
try-finally without any except blocks. Your code is equivalent to this:

def goto_is_dead(n):
     try:
         if n == 0 or n == 1 or n == 2:
             # if you're validating input, validate the input
             print "Error Input %s" % n
         else:
             print "Good Input %s inv= %s" % (n, (1. / n))
     finally:
         print "any input %s" % n

if __name__ == '__main__':
     goto_id_dead(0)
     goto_id_dead(2)
     goto_id_dead(3)

More concise, readable, and maintainable.

-Matt- Hide quoted text -

- Show quoted text -

as mentioned 'in complex code the goto statement is still the easiest
to code and understand'.
The examples are very small and do not require that at all. I agree
it's ugly.
Just to show a way to do it.

A very few functions where I use goto in C or C# are a few hundred
lines of code, difficult to split in smaller functions.
A lot of common data.
One coming to my mind is a complex validation function for the user
input of a complex transaction.
If any test fails, goto the cleaning part and issue error message.

The goto code is the simpler way to do it.
We are not talking about simple if-else, but let say 20 if-else.
Many nested if-else are more difficult to understand and do not fit
better the semantics.
 
F

Fredrik Lundh

The goto code is the simpler way to do it.
We are not talking about simple if-else, but let say 20 if-else.
Many nested if-else are more difficult to understand and do not fit
better the semantics.

let's see...

$ cd ~/svn/python25
$ grep goto */*.c | wc
2107 7038 86791

but given that the Python language doesn't have a goto statement, can we
perhaps drop this subtopic now?

</F>
 
M

Matthew Fitzgibbons

as mentioned 'in complex code the goto statement is still the easiest
to code and understand'.
The examples are very small and do not require that at all. I agree
it's ugly.
Just to show a way to do it.

A very few functions where I use goto in C or C# are a few hundred
lines of code, difficult to split in smaller functions.
A lot of common data.
One coming to my mind is a complex validation function for the user
input of a complex transaction.
If any test fails, goto the cleaning part and issue error message.

The goto code is the simpler way to do it.
We are not talking about simple if-else, but let say 20 if-else.
Many nested if-else are more difficult to understand and do not fit
better the semantics.

I'm sorry, but if you have any single function that's a few hundred
lines of code, you need to do some serious refactoring. How do you even
begin to test that? A goto is just a hack that hides underlying
problems. If I see a function of more than about twenty lines or having
more than two or three execution paths, I start thinking of ways to
break it down.

There are a lot of approaches. Paul Hankin put all the conditionals in a
helper function. Similarly, you could do something like this (for more
fun make the validators pluggable):

# each validator is a function that takes the input the be validated
# and returns True for good input; otherwise False
_foo_validators = [_check_this, _check_that, _check_the_other] # etc.

def foo(input):
for v in _validators:
if not v(input):
_on_bad_input(input)
break
else:
_on_good_input(input)
_on_all_input(input)

Alternatively, you can often turn complex input validation into a state
machine.

-Matt
 
R

Reedick, Andrew

-----Original Message-----
From: [email protected] [mailto:python-
[email protected]] On Behalf Of Kurien Mathew
Sent: Saturday, August 16, 2008 5:21 PM
To: (e-mail address removed)
Subject: Good python equivalent to C goto

Hello,

Any suggestions on a good python equivalent for the following C code:

while (loopCondition)
{
if (condition1)
goto next;
if (condition2)
goto next;
if (condition3)
goto next;
stmt1;
stmt2;
next:
stmt3;
stmt4;
}


===========================
Use a flag and a one loop for loop


while loopCondition:
flag = False
for i in range(1):
if condition1:
break
if condition2:
break
if condition3:
break
stmt1
stmt2
flag = True
if not flag:
stmt3
stmt4


===========================
Or just a straight flag

while ( loopCondition ):
flag = False

if (condition1)
flag = True # goto next;
if (not flag and condition2)
flag = True # goto next;
if (not flag and condition3)
flag = True # goto next;

if not flag:
stmt1
stmt2
else
stmt3
stmt4



*****

The information transmitted is intended only for the person or entity to which it is addressed and may contain confidential, proprietary, and/or privileged material. Any review, retransmission, dissemination or other use of, or taking of any action in reliance upon this information by persons or entities other than the intended recipient is prohibited. If you received this in error, please contact the sender and delete the material from all computers. GA622
 
P

Paul McGuire

I would not be too happy if I saw C code like that in my repository.
This is equivalent:

while (loopCondition) {
     if (!(condition1 || condition2 || condition3)) {
         stmt1;
         stmt2;
     }
     stmt3;
     stmt4;

}

In Python:

while (loopCondition):
     if not (condition1 or condition2 or condition3):
         stmt1
         stmt2
     stmt3
     stmt4

If stmt3 and stmt4 are error cleanup code, I would use try/finally.

while loopCondition:
     try:
         if condition1:
             raise Error1()
         if condition2:
             raise Error2()
         if condition3:
             raise Error3()
         stmt1
         stmt2
     finally:
         stmt3
         stmt4

This will also bail out of the loop on and exception and the exception
will get to the next level. If you don't want that to happen, put an
appropriate except block before the finally.

-Matt- Hide quoted text -

- Show quoted text -

Close, but there is no reason for the conditions to raise anything,
they can just use the continue statement:

i = 20
while i > 0:
try:
if i % 2:
continue
if i % 3:
continue
print i, "is even and a multiple of 3"
finally:
i -= 1

Prints:
18 is even and a multiple of 3
12 is even and a multiple of 3
6 is even and a multiple of 3

I think this is closest to the OP's stated requirements.

-- Paul
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,769
Messages
2,569,580
Members
45,055
Latest member
SlimSparkKetoACVReview

Latest Threads

Top