Hayden
Hayden

Reputation: 167

How to make a function inside another function quit both functions at once?

I'm making a program that asks the users some questions and uses different functions to react to what the user gives as input. I need to make it such that if the user ever types "Cancel", it will not only end the function they are currently in but even the function that called the prior function.

def func1(x):
    func2(x+5)
    print 5
def func2(x):
    func3(x+5)
    print 5
def func3(x):
    print x
    return

func1(20)
print 10

# 30
# 5
# 5
# 10

So currently this will print 30, exit func3, print 5, exit func2, print 5, exit func1. I need a way for it to just stop after func3 prints 30. Any ideas?

So the desired output would be.

#30
#10

Edit: This is an extremely simplified version, they wouldn't type cancel in this specific code. It would be in a raw_input.

Upvotes: 1

Views: 191

Answers (1)

Nishant
Nishant

Reputation: 21934

Raising an exception quits the function stack just like the way you are describing. So you can have the outermost function try-expect all the inner functions. If any of the inner function raises an exception, it will bubble up (i.e it won't execute any of the subsequent code in the stack) until it reaches the outermost function's except.

def func1(x):
    try:
      func2(x+5)
      print 5
    except:
      pass  

def func2(x):
    func3(x+5)
    print 5

def func3(x):
    print x
    raise("Foo")  # user's input should drive this.
    return

func1(20)
print 10

It reaches till func3 in a normal way. func3 however says it doesn't want the normal execution flow to func2 which cascades it to func1.

If you don't want to change the function's content you can use the following decorator. It also has the corrections mentioned in the comments.

class UserAbort(Exception):
    pass

def swallow(f):
    def wrapper(*args):
        try:
            f(*args)
        except UserAbort:
            pass
    return wrapper

@swallow
def func1(x):
    func2(x+5)
    print 5

def func2(x):
    func3(x+5)
    print 5

def func3(x):
    print x
    raise UserAbort  # user's input should drive this.
    return

func1(20)
print 10

Upvotes: 3

Related Questions