Tuples vs. variable-length argument lists
Steven D'Aprano
steve at REMOVE-THIS-cybersource.com.au
Sat Mar 20 04:20:38 CET 2010
On Fri, 19 Mar 2010 17:20:31 -0700, Spencer Pearson wrote:
> Hi!
>
> This might be more of a personal-preference question than anything, but
> here goes: when is it appropriate for a function to take a list or tuple
> as input, and when should it allow a varying number of arguments?
That depends on the function as well as your personal preference.
Of course, you can also follow the lead of max and min and accept both:
>>> max(1, 2, 3, 4) == max([1, 2, 3, 4])
True
You need to consider which is more "natural" for the semantics of the
function.
> It seems as though the two are always interchangeable.
Not always. Consider sum(a, b, c, d).
Should that be "sum the sequence [a, b, c, d]" or "sum the sequence [a,
b, c] with initial value d"? You might ask what difference it makes, but
it may make a big difference:
* if a...d are floats, there may be differences in rounding errors
between a+b+c+d and d+a+b+c
* if a...d are lists, the order that you do the addition matters:
["a", "b", "c"] + ["d"] != ["d"] + ["a", "b", "c"]
* even if a...d are integers, it may make a big difference for
performance. Perhaps not for a mere four arguments, but watch:
>>> n = 10**1000000
>>> seq = [n] + range(10001)
>>> from timeit import Timer
>>> t1 = Timer("sum(seq)", "from __main__ import n, seq; seq.append(-n)")
>>> t2 = Timer("sum(seq, -n)", "from __main__ import n, seq")
>>> min(t1.repeat(number=1))
6.1270790100097656
>>> min(t2.repeat(number=1))
0.012988805770874023
In the first case, all the intermediate calculations are done using a
million digit long int, in the second case it is not.
[...]
> I can't think
> of any situation where you couldn't convert from one form to the other
> with just a star or a pair of parentheses.
Of course you can convert, but consider that this is doing a conversion.
Perhaps that's unnecessary work for your specific function? You are
packing and unpacking a sequence into a tuple. Whether this is a good
thing or a bad thing depends on the function.
> Is there a generally accepted convention for which method to use? Is
> there ever actually a big difference between the two that I'm not
> seeing?
If you think of the function as operating on a single argument which is a
sequence of arbitrary length, then it is best written to take a single
sequence argument.
If you think of the function as operating on an arbitrary number of
arguments, then it is best written to take an arbitrary number of
arguments.
If you think it doesn't matter, then choose whichever model is less work
for you.
If neither seems better than the other, then choose arbitrarily.
If you don't like the idea of making an arbitrary choice, or if your
users complain, then support both models (if possible).
--
Steven
More information about the Python-list
mailing list