Q: We have *args and **kwargs. Woud ***allargs be useful?
Jon Clements
joncle at googlemail.com
Thu Apr 1 11:38:40 EDT 2010
On 1 Apr, 10:57, Jonathan Fine <J.F... at open.ac.uk> wrote:
> The idioms
> def f(*args, **kwargs):
> # Do something.
> and
> args = (1, 2, 3)
> kwargs = dict(a=4, b=5)
> g(*args, **kwargs)
> are often useful in Python.
>
> 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.
More information about the Python-list
mailing list