# Re: passing variable length arguments without unpacking them

Tim Peters (tim@ksr.com)
Tue, 26 Jan 93 21:18:25 EST

> I'm using python 0.9.8 and try to use the variable length arguments
> ...
> I cannot arbitrarily pass along a set of arguments without interpreting
> them. For example (albeit articifial):
>
> count = 10
> def recurse(*args):
> global count
> count = count - 1
> if (count == 0): one, two, three = args
> else: recurse(args)
>
> recurse(1, 2, 3)
>
> This will fail. ...

Let me stick in a print so it's easier to see why it fails:

count = 10
def recurse(*args):
global count
print 'Entering recurse, count =', count, 'args =', args
count = count - 1
if (count == 0): one, two, three = args
else: recurse(args)

This yields:

>>> recurse(1,2,3)
Entering recurse, count = 10 args = (1, 2, 3)
Entering recurse, count = 9 args = ((1, 2, 3),)
Entering recurse, count = 8 args = (((1, 2, 3),),)
Entering recurse, count = 7 args = ((((1, 2, 3),),),)
Entering recurse, count = 6 args = (((((1, 2, 3),),),),)
Entering recurse, count = 5 args = ((((((1, 2, 3),),),),),)
Entering recurse, count = 4 args = (((((((1, 2, 3),),),),),),)
Entering recurse, count = 3 args = ((((((((1, 2, 3),),),),),),),)
Entering recurse, count = 2 args = (((((((((1, 2, 3),),),),),),),),)
Entering recurse, count = 1 args = ((((((((((1, 2, 3),),),),),),),),),)
ValueError: unpack tuple of wrong size
Stack backtrace (innermost last):
File "<stdin>", line 1
File "./temp.py", line 7
else: recurse(args)
File "./temp.py", line 7
else: recurse(args)
File "./temp.py", line 7
else: recurse(args)
File "./temp.py", line 7
else: recurse(args)
File "./temp.py", line 7
else: recurse(args)
File "./temp.py", line 7
else: recurse(args)
File "./temp.py", line 7
else: recurse(args)
File "./temp.py", line 7
else: recurse(args)
File "./temp.py", line 7
else: recurse(args)
File "./temp.py", line 6
if (count == 0): one, two, three = args
>>>

I understand that this isn't what you want, but the rule does seem clear
& consistent: a "*" formal argument sees a tuple comprising the actual
arguments. The behavior of recurse is at least predictable given that.
And at least I find it very natural <grin>.

Your problem is that, in trying to pass the argument list on, you're
actually passing a tuple instead of the original argument list. The
built-in function "apply" goes the other direction, making a tuple act as
if it were an argument list. This solves the problem nicely:

count = 10
def rec2(*args):
global count
print 'Entering rec2, count =', count, 'args =', args
count = count - 1
if (count == 0): one, two, three = args
else: apply(rec2,args) # only line that's substantially different

This yields:
>>> rec2(1,2,3)
Entering rec2, count = 10 args = (1, 2, 3)
Entering rec2, count = 9 args = (1, 2, 3)
Entering rec2, count = 8 args = (1, 2, 3)
Entering rec2, count = 7 args = (1, 2, 3)
Entering rec2, count = 6 args = (1, 2, 3)
Entering rec2, count = 5 args = (1, 2, 3)
Entering rec2, count = 4 args = (1, 2, 3)
Entering rec2, count = 3 args = (1, 2, 3)
Entering rec2, count = 2 args = (1, 2, 3)
Entering rec2, count = 1 args = (1, 2, 3)
>>>

> In reality I'm using this in class initialization routines, where I try
> to do something like: [a reasonable thing to want to do deleted] ...

I confess I didn't try it, but I _believe_ the same technique will solve