Python - Returning a break statement - python

If you call a function to check exit conditions, can you have it return a break statement? Something like:
def check():
return break
def myLoop:
while myLoop:
check()
Is there anything like this allowed? I know the syntax as written isn't valid.

No, it doesn't work like that unfortunately. You would have to check the return value and then decide to break out of the loop in the caller.
while myLoop:
result = check()
if result == 'oh no':
break
Of course, depending on what you are trying to do, it may just be as simple as:
result = check()
while result != 'oh no':
result = check()

break is a keyword but not an object so it is treated differently by the interpreter, link. Python function can only return objects or the like.
If you want to break out of a loop when deep inside functions, one way is to use an exception:
class BreakException(Exception):
pass
Raise the exception somewhere in a function:
def some_func():
raise BreakException()
And you can break out of a loop like this:
try:
while True:
some_func()
except BreakException:
pass
I do not feel this is good practice, but have seen some language using it, Scala for example link.

def check():
#define your conditions here with if..else statement
return True
def myLoop():
while True:
if check()==True: break

Related

How do I move on to the next element in my list based on some condition satisfied in a function I have called?

I have the following code:
def check_if_number_is_5(x):
try:
#some code
except Exception as e:
#some code
for x in some_list:
#Some code
check_if_number_is_5(x)
#Rest of the code
Basically, I want to move on to the next element in my list if that condition is satisfied and I don't want #Rest of the code to run.
Is there anyway to do this without returning a boolean value and having another conditional statement. I have explored doing this with an exception but the problem is the exception is being caught with by the except block of the function.
The key is the continue statement, to move on to the next iteration, but you need a triggerer, for that, there is 2 ways :
the boolean one
def check_if_number_is_5(x):
try:
# some code
return True
except Exception as e:
# some code
return False
some_list = []
for x in some_list:
# Some code
if check_if_number_is_5(x):
continue
# Rest of the code
the exception one
def check_if_number_is_5(x):
try:
# some code
pass
except Exception as e:
# some code
raise Exception()
some_list = []
for x in some_list:
# Some code
try:
check_if_number_is_5(x)
except:
continue
# Rest of the code
so the function would look like somewhat this:
don't catch error in the function
def check_if_number_is_not_5(x):
if x==5:
return False
return True
In the code call the function and check return value then use the break to breakout of loop.
some_list = []
for x in some_list:
# code
if check_if_number_is_not_5(x):
break
# code

Why can't I return break? What should I use instead?

How can I stop my loop from a function? Why can't I return break?
This is some sample code.
def example():
#a process goes here
return break
while 1:
example()
I get an invalid syntax error.
Have example() return a boolean to indicate that the loop should break:
def example():
#a process goes here
return True # True to break / False to keep going
while True: # True is more explicit than 1
if example():
break
Note that in the particular example you gave, the loop could just be
while example():
pass # Or whatever code goes afterwards
You do not need to return break, you can just return from the loop based on the condition, as there is no way to return breaks in python :
def example():
#a process goes here
return
while 1:
example()
Alternatively, you can set a variable which stores a value when it stops :
run = True
while run:
# ...
if condition is True:
run = True
else:
run = False
# ...

Python3 variable passing issue

Example code, try to ignore how it is seems unnecessarily overcomplicated- this is way dumbed down from the actual code, but mimics the flow exactly.
def setup():
print("Setting up...")
do_something()
def do_something():
task = str(input("Enter a task to do: "))
try:
print("Doing {}...".format(task))
except:
print("Failed to do {}...".format(task))
finally:
return task
def choose_2(choice):
print("You chose {}".format(choice))
def menu_1():
choice = int(input("Choose 1 or 2: "))
if choice == 1:
setup()
menu_2(task)
menu_1()
However, the program returns "UnboundLocalError: local variable 'task' referenced before assignment"
Why is do_something() not returning the variable task to the if statement within menu_1()? Once setup() (and subsequently do_something()) finishes running, shouldn't do_something()'s returned value remain inside the if statement, since it's not done yet?
The flow is :
menu_1() => menu_2(task)
task has not been defined in the scope of menu_1() so it has no way of being defined.
You may have intended to do this instead:
def setup():
print("Setting up...")
return do_something()
.....
# in menu_1():
menu_2(setup())
Notice that because setup now RETURNS something, it can have that return value used.
setup() and menu_1() function should be changed like this:
def setup():
print("Setting up...")
do_something()
def menu_1():
choice = int(input("Choose 1 or 2: "))
if choice == 1:
task=setup()
menu_2(task)
Explanation:
menu_1() calls setup(), setup() calls do_something(). Now 'do_something()' will return the value of task but you are not returning it from 'setup()' function to menu_1() and then in menu_1() you have to store the returned value in a variable named 'task'.

Short form to return method result if condition passed

I'm wondering if there's any pythonic or short-form method to achieve the following:
error_response = self.check_conditions(request)
# If we have an error response, return it, otherwise continue as normal.
if error_response:
return error_response
Something like:
(return self.check_conditions(request)) or pass
Alternatively, is it possible for a function to return the calling method, such as:
self.check_conditions(request)
def check_conditions(self, request):
error_response = do_stuff()
if error_response:
return_parent error_response
I get the feeling the second concept is breaking a ton of programming laws to prevent chaos and the apocalypse, just a thought though :)
No, there is no short form for a conditional return.
But, to get to the second part of your question:
There are exceptions in Python. You can write something like this:
class MyErrorResponse(Exception): pass
class MyClass:
...
def check_conditions(self, request):
error_response = do_stuff()
if error_response:
raise MyErrorResponse(error_response)
def do_the_main_stuff():
try:
self.check_conditions()
...
except MyErrorResponse as e:
return e.args[0]
That depends a lot on what check_conditions does under the hood. It's likely that you can move error handling down a level of abstraction and handle things directly:
Compare:
error = False
def foo(request):
global error
try:
result = do_something_with(request)
except SomeWellDefinedError:
error = True
def check_conditions(request):
foo(request)
return error
def main():
error_response = check_conditions(some_request)
if error_response:
# freak out!
With
def foo(request):
try:
result = do_something_with(request)
except SomeWellDefinedError:
# you can try to handle the error here, or...
raise # uh oh!
def main():
try:
foo(some_request)
except SomeWellDefinedError:
# handle the error here, instead!

Catch exception and continue try block in Python

Can I return to executing the try block after exception occurs?
For example:
try:
do_smth1()
except:
pass
try:
do_smth2()
except:
pass
vs.
try:
do_smth1()
do_smth2()
except:
??? # magic word to proceed to do_smth2() if there was exception in do_smth1
No, you cannot do that. That's just the way Python has its syntax. Once you exit a try-block because of an exception, there is no way back in.
What about a for-loop though?
funcs = do_smth1, do_smth2
for func in funcs:
try:
func()
except Exception:
pass # or you could use 'continue'
Note however that it is considered a bad practice to have a bare except. You should catch for a specific exception instead. I captured for Exception because that's as good as I can do without knowing what exceptions the methods might throw.
While the other answers and the accepted one are correct and should be followed in real code, just for completeness and humor, you can try the fuckitpy ( https://github.com/ajalt/fuckitpy ) module.
Your code can be changed to the following:
#fuckitpy
def myfunc():
do_smth1()
do_smth2()
Then calling myfunc() would call do_smth2() even if there is an exception in do_smth1())
Note: Please do not try it in any real code, it is blasphemy
You can achieve what you want, but with a different syntax. You can use a "finally" block after the try/except. Doing this way, python will execute the block of code regardless the exception was thrown, or not.
Like this:
try:
do_smth1()
except:
pass
finally:
do_smth2()
But, if you want to execute do_smth2() only if the exception was not thrown, use a "else" block:
try:
do_smth1()
except:
pass
else:
do_smth2()
You can mix them too, in a try/except/else/finally clause.
Have fun!
'continue' is allowed within an 'except' or 'finally' only if the try block is in a loop. 'continue' will cause the next iteration of the loop to start.
So you can try put your two or more functions in a list and use loop to call your function.
Like this:
funcs = [f,g]
for func in funcs:
try: func()
except: continue
For full information you can go to this link
You could iterate through your methods...
for m in [do_smth1, do_smth2]:
try:
m()
except:
pass
one way you could handle this is with a generator. Instead of calling the function, yield it; then whatever is consuming the generator can send the result of calling it back into the generator, or a sentinel if the generator failed: The trampoline that accomplishes the above might look like so:
def consume_exceptions(gen):
action = next(gen)
while True:
try:
result = action()
except Exception:
# if the action fails, send a sentinel
result = None
try:
action = gen.send(result)
except StopIteration:
# if the generator is all used up, result is the return value.
return result
a generator that would be compatible with this would look like this:
def do_smth1():
1 / 0
def do_smth2():
print "YAY"
def do_many_things():
a = yield do_smth1
b = yield do_smth2
yield "Done"
>>> consume_exceptions(do_many_things())
YAY
Note that do_many_things() does not call do_smth*, it just yields them, and consume_exceptions calls them on its behalf
I don't think you want to do this. The correct way to use a try statement in general is as precisely as possible. I think it would be better to do:
try:
do_smth1()
except Stmnh1Exception:
# handle Stmnh1Exception
try:
do_smth2()
except Stmnh2Exception:
# handle Stmnh2Exception
Depending on where and how often you need to do this, you could also write a function that does it for you:
def live_dangerously(fn, *args, **kw):
try:
return fn(*args, **kw)
except Exception:
pass
live_dangerously(do_smth1)
live_dangerously(do_smth2)
But as other answers have noted, having a null except is generally a sign something else is wrong with your code.
This can be done with exec() in a custom function, a list of strings, and a for loop.
The function with exec():
def try_it(string):
try:
exec(string)
print(f'Done: {string}')
except:
print(f'Error. Could not do: {string}')
More on exec():
exec(object)
This function supports dynamic execution of Python code. object must be either a string or a code object.
Example list of strings and for loop:
do_smth_list = ['do_smth1()', 'do_smth2()', 'do_smth3()']
for smth in do_smth_list:
try_it(smth)
This definitely isn't the cleanest way of doing it, but you can put it in a while loop with a variable set to true, and when it runs the function successfully it sets the variable to false, whereas if it fails it keeps the variable set to true.
x = True
while x == True:
try:
do_smth1()
do_smth2()
x = False
except Exception:
x = True
This way what happens is that the while loop will keep on looping the try except section again and again until it works, in which x is set to false and the loop stops
Also, you can implement a break in the while loop instead of basing it on a variable, for example:
while True:
try:
do_smth1()
do_smth2()
break
except Excpetion:
pass
P.S It is good ettiquete to put a specific exception for the except section, instead of leaving it for any exception. It makes the code cleaner and is more sensible when managing errors especially in bigger projects
special_func to avoid try-except repetition:
def special_func(test_case_dict):
final_dict = {}
exception_dict = {}
def try_except_avoider(test_case_dict):
try:
for k,v in test_case_dict.items():
final_dict[k]=eval(v) #If no exception evaluate the function and add it to final_dict
except Exception as e:
exception_dict[k]=e #extract exception
test_case_dict.pop(k)
try_except_avoider(test_case_dict) #recursive function to handle remaining functions
finally: #cleanup
final_dict.update(exception_dict)
return final_dict #combine exception dict and final dict
return try_except_avoider(test_case_dict)
Run code:
def add(a,b):
return (a+b)
def sub(a,b):
return (a-b)
def mul(a,b):
return (a*b)
case = {"AddFunc":"add(8,8)","SubFunc":"sub(p,5)","MulFunc":"mul(9,6)"}
solution = special_func(case)
Output looks like:
{'AddFunc': 16, 'MulFunc': 54, 'SubFunc': NameError("name 'p' is not defined")}
To convert to variables:
locals().update(solution)
Variables would look like:
AddFunc = 16, MulFunc = 54, SubFunc = NameError("name 'p' is not defined")
If do_smth1() worked, then do_smth2() will not be tried.
try:
x=do_smth1()
except:
try:
x=do_smth2()
except:
x="Both Failed"
print (x)

Categories