I'm finding myself picking up /all/ the arguments and storing them for
later use (as part of a testing framework). So for me it would be nice
if I could write
def f(***allargs):
args, kwargs = allargs
# Continue as before.
However, if we do this then 'args' in '*args' is misleading. So I'll
use 'sargs' (for sequence arguments) instead.
I can now write, for a suitable class Args
args = Args(1, 2, 3, a=4, b=5)
g(***args) # Same as before.
sargs, kwargs = args
g(*sargs, **kwargs) # Same as before.
Even better, now that Args is a class we can give it a method 'call' so that
args.call(g)
is equivalent to
g(***args)
which removes the need for the *** construct.
This reminds me of functools.partial except, of course, we've fixed all
the arguments and left the passing of the function for later, whereas in
partial we fix the function and some of the arguments.
http://docs.python.org/library/functools.html#functools.partial
My view are that
1. Conceptually ***allargs is useful, but an Args class would be more
useful (not that it need be either-or).
2. If Args were built in , there could be performance benefits.
3. It's clearer to write
def(*seqargs, **kwargs):
than
def(*args, **kwargs):
4. When the Args class is used a lot, one might welcome
def(***args):
# Do something with args.
as a shortcut (and minor speedup) for
def(*seqargs, **kwargs):
args = Args(*seqargs, **kwargs)
# Do something with args.
I look forward to your comments on this.
--
Jonathan
I'm not sure this'll catch on, it'll be interesting to see other
comments.
However, I believe you can get the behaviour you desire something
like:
import inspect
class AllArgs(object):
def __init__(self, func):
self._func = func
self._spec = inspect.getargspec(func)
self._nposargs = len(self._spec.args)
def __call__(self, *args, **kwdargs):
self._func.func_globals['Args'] = (args[self._nposargs:],
kwdargs)
return self._func(*args[:self._nposargs])
@AllArgs
def test():
print Args
@AllArgs
def test2(a, b):
print a, b, Args
test(1, 2, 3, 4, 5, a=3, b=5)
test2(1, 2, 3, 4, 5, c=7)
Done quickly, probably buggy, but does provide 'Args', but without
further work
swallows any *'s and **'s and might ignore defaults (hideously
untested)
hth
Jon.
Thank you for your interest, Jon.
According to http://docs.python.org/library/inspect.html we have that
func_globals is the global namespace in which this function was defined.
Hence we have
>>> def f(): pass
...
>>> f.func_globals is globals()
True
>>> f.func_globals ['x'] = 3
>>> x
3
>>>
I don't yet understand what your code is intended to do, but I'm fairly
sure you're not wishing to 'monkey-patch' a global namespace of a module.
--
Jonathan