Say I have a function F that may return boolean false. If I have a caller named main() that will call F in multiple places, can I attach a decorator to F that will propagate the return value and cause its parent (main) to also exit early?
No function can 'return' to a context higher than it's caller. This (to my knowledge) is universal in most programming languages. You could probably hack it by inspecting the python state and call stack, but a much better / more appropriate solution would be to wrap main in a try: except:
block that catches a custom exception that you raise inside this decorator depending on the output of F()
import random
from functools import wraps
class ShortCircuit(Exception):
pass
def short_circuit(f):
@wraps(f)
def wrapped(*args, **kwargs):
res = f(*args, **kwargs)
if not res:
raise ShortCircuit()
else:
return res
return wrapped
@short_circuit
def F():
return random.choice([True, False])
def main():
print(F())
print(F())
if __name__=="__main__":
try:
main()
except ShortCircuit:
print("short circuited")