Shortcutting the function call stack

Jason tenax.raccoon at gmail.com
Mon Mar 24 10:48:04 EDT 2008


On Mar 24, 5:21 am, Julien <jpha... at gmail.com> wrote:
> Hello all,
>
> I would like to do something like:
>
> def called(arg)
>     if arg==True:
>         !!magic!!caller.return 1
>
> def caller(arg)
>     called(arg)
>     return 2
>
> Here, the fake !!!magic!!! represents a statement (which I ignore)
> that would make the caller function return a value different from what
> it'd return normally.
>
> For example, caller(True) would return 1, and caller(False) would
> return 2. The reason I want that is because I don't want the caller
> function to know what's going on in the called function, and be
> shortcut if the called function think it's necessary.
>
> Would you know if that's possible, and if so, how?
>
> I've done a bit of research and I think I've found some good pointers,
> in particular using the 'inspect' library:
>
> import inspect
>
> def called(arg)
>     if arg==True:
>         caller_frame = inspect.stack()[1]
>         ...
>
> Here 'caller_frame' contains the frame of the caller function. Now,
> how can I make that frame return a particular value?
>
> By the way, I'm not really interested in 'called' throwing an
> exception and 'caller' catching it. In fact, I want things to remain
> completely transparent for 'caller'.
>
> Hope that was clear... :/
>
> Thanks!
>
> Julien

As Steven wrote, it's not very clear.  If we knew the intent of this,
we could perhaps point you to a more useful, maintainable technique.
We don't know why you're trying to circumvent the programming language
in this case.  Any solution that works as you described will probably
be unportable between the different Pythons (CPython, Jython,
IronPython, etc).

Please note that the following code should work, but I've only run it
through the interpreter in my brain.  My brain's interpreter is full
of Heisenbugs, so you may need to adjust a few things.  Here's my
thoughts:

Given:
    def First( arg ):
        Second( arg )
        return 5

1)  If you can modify both functions, change the first function to
return a value in certain circumstances:
    def AltFirst( arg ):
        value = Second( arg )
        if value is not None:  return value
        return 5

2)  Raise an exception in Second, and catch that exception above
First:

class SecondExcept(Exception):
    def __init__(self, value):
        Exception.__init__(self, 'Spam!')
        self.value = value

def Second(arg):
    if arg == my_conditional_value:
        raise SecondExcept( 5 )

# The following could even be put in your own function,
# or in a wrapper or decorator for the First function.
try:
    myvalue = First( 'Vikings!' )
except SecondExcept, exc:
    myvalue = exc.value

When you need to use an exceptional pathway, use an exception.  They
aren't just for reporting errors.

Hope this helps.

  --Jason



More information about the Python-list mailing list