Shortcutting the function call stack
Arnaud Delobelle
arnodel at googlemail.com
Mon Mar 24 19:26:34 EDT 2008
On Mar 24, 10:05 pm, Julien <jpha... at gmail.com> wrote:
> Hi all, and thanks a lot for your answers!
>
> I'll try to explain a bit more what I'm after, and hopefully that will
> be clearer. In fact, what I'm trying to do is to "hijack" (I'm making
> up the term) a function:
>
> def hijacker(arg):
> if I_feel_its_necessary:
> hijack_caller_function_and_make_it_return(1)
>
> def my_function1(arg):
> hijacker(something)
> ... # Continue as normal
> return 2
>
> def my_function2(arg):
> ... # Maybe do some processing here
> hijacker(whatever)
> ... # Continue as normal
> return 3
>
> I have some long functions like my_function1 and my_function2 which
> I'd like to alter, but I want to keep the alterations as little as as
> possible. I'd like the extra behaviour to be handled by 'hijacker' and
> let it decide what the caller function should return. Just adding a
> call to 'hijacker' in all of these functions would be ideal for me
> because that would be quick to modify them and also easier to
> maintain, I believe.
>
> If 'hijacker' thinks it's necessary, it would force the caller
> function to return a certain
> value, otherwise it would let the caller function do its normal
> business.
>
> For while I thought I'd make hijacker a decorator:
>
> @hijacker
> def my_function(request):
> ....
>
> But that wouldn't work, since some functions need to do some
> processing before calling the hijacker. Yet, I think a decorator is
> systematically called before the function itself so no prior
> processing can be done by the function...
>
> Any idea on how to do that, if that's even possible?
Of course it's possible ;), with the combination of an exception and a
decorator. See example below. However I would seriously doubt the
maintainability of such practices...
# --------- hijack.py ------------
from functools import wraps
class HijackReturn(Exception):
def __init__(self, val):
self.val = val
def hijack(f):
@wraps(f)
def hijacked(*args, **kwargs):
try:
return f(*args, **kwargs)
except HijackReturn, e:
return e.val
return hijacked
@hijack
def foo(x):
x = x + 1
hijacker(x)
return x * 2
def hijacker(x):
if x == 21:
print "[Oh no, it's going to be 42!]"
raise HijackReturn(41)
# -------------------------------
marigold:junk arno$ python -i hijack.py
>>> foo(10)
22
>>> foo(20)
[Oh no, it's going to be 42!]
41
>>>
HTH
--
Arnaud
More information about the Python-list
mailing list