Shortcutting the function call stack

castironpi at gmail.com castironpi at gmail.com
Mon Mar 24 11:06:01 EDT 2008


On Mar 24, 9:48 am, Jason <tenax.racc... at gmail.com> wrote:
> 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.

Exceptions are a control tool.  There was a 'goto using Exceptions'
once in the manuals.  I don't see a problem with a local control-flow
object.  It would appease a number of requests I've read.

for x:
  for y:
    control.break( 2 )

if a:
  if b:
    control.fail( 2 )

so no need to reduplicate:

  else:
    thing()
else:
  thing()

if a:
  if b:
    control.mostrecenttest( 0 )

def f():
  def g():
    control.return( 2 )( "early" )

Something tells me generators could solve the problem, but I may be
enamored, so it's a separate post.



More information about the Python-list mailing list