By using this site, you agree to our updated Privacy Policy and our Terms of Use. Manage your Cookies Settings.
439,942 Members | 1,788 Online
Bytes IT Community
+ Ask a Question
Need help? Post your question and get tips & solutions from a community of 439,942 IT Pros & Developers. It's quick & easy.

Preserving the argspec of a function after generating a closure

P: n/a
Is there a way to preserve the argspec of a function after wrapping it
in a closure?

I'm looking for a general way to say "wrap function F in a closure",
such that inspect.getargspec on the closure would return the same
(args, varargs, varkw, defaults) tuple ass the enclosed function.

The typical code I'm using is something like this:

def wrapFunc(func):
def tmpWrapper(*args, **kwargs):
return func(*args, **kwargs)
tmpWrapper.func_name = func.func_name
return wrapFunc

This preserves the function name - how do I do more?

vic

--
"Never attribute to malice that which can be adequately explained by
stupidity." - Hanlon's Razor
Jul 18 '05 #1
Share this Question
Share on Google+
1 Reply


P: n/a
On Fri, 11 Mar 2005 11:55:51 -0500, Victor Ng <cr*********@gmail.com> wrote:
Is there a way to preserve the argspec of a function after wrapping it
in a closure?

I'm looking for a general way to say "wrap function F in a closure",
such that inspect.getargspec on the closure would return the same
(args, varargs, varkw, defaults) tuple ass the enclosed function.

The typical code I'm using is something like this:

def wrapFunc(func):
def tmpWrapper(*args, **kwargs):
return func(*args, **kwargs)
tmpWrapper.func_name = func.func_name
return wrapFunc

This preserves the function name - how do I do more?

Probably you could use the inspect.getargspec(func) info to
build a wrapper with the identical signature that would call func
passing everything through 1:1, but that would seem kind of useless, unless
you want to substitute some closure values into the func call and get
a currying effect. In that case, your new signature should probably be changed
to reflect the real effective signature of the curried function.

I recently posted a byte-code-munging decorator hack that accomplishes some of that. E.g.,
(I keep presets.py in my ut package, where I accumulate miscellaneous experimental untility stuff)
from ut.presets import presets, curry
@curry(y=123) ... def foo(x, y): return x*y
... import inspect
inspect.getargspec(foo) (['x'], None, None, None) import dis
dis.dis(foo) 1 0 LOAD_CONST 1 (123)
3 STORE_FAST 1 (y)

3 6 LOAD_FAST 0 (x)
9 LOAD_FAST 1 (y)
12 BINARY_MULTIPLY
13 RETURN_VALUE

And without the currying decorator:
def foo(x, y): return x*y ... inspect.getargspec(foo) (['x', 'y'], None, None, None) dis.dis(foo) 1 0 LOAD_FAST 0 (x)
3 LOAD_FAST 1 (y)
6 BINARY_MULTIPLY
7 RETURN_VALUE
Basically, the curry decorator here injects a local assignment and adjusts the line map
and signature and a few other tweaks, depending.

This doesn't wrap the function though, it modifies it.
I haven't tried decorating indirectly... Hm...
Faking decoration of foo with getf to substitute the func passed ...
def wrap(func, y): ... def getf(f): return func
... @curry(y=y)
... @getf
... def foo(): pass
... foo.func_name = func.func_name
... return foo
... def bar(x, y): return x+y ... wbar = wrap(bar, 1000)
wbar <function bar at 0x02F1AAE4> bar(123) Traceback (most recent call last):
File "<stdin>", line 1, in ?
TypeError: bar() takes exactly 2 arguments (1 given)

oops, that should have been wbar ...
wbar(123) 1123 inspect.getargspec(wbar) (['x'], None, None, None) import dis
dis.dis(wbar) 1 0 LOAD_CONST 1 (1000)
3 STORE_FAST 1 (y)

3 6 LOAD_FAST 0 (x)
9 LOAD_FAST 1 (y)
12 BINARY_ADD
13 RETURN_VALUE
inspect.getargspec(bar) (['x', 'y'], None, None, None) dis.dis(bar)

1 0 LOAD_FAST 0 (x)
3 LOAD_FAST 1 (y)
6 BINARY_ADD
7 RETURN_VALUE

I don't know where this is leading. What was your goal again?

Regards,
Bengt Richter
Jul 18 '05 #2

This discussion thread is closed

Replies have been disabled for this discussion.