The function definition below comes from the itertools recipes page (https://docs.python.org/2/library/itertools.html#recipes).

def random_product(*args, **kwds):
    "Random selection from itertools.product(*args, **kwds)"
    pools = map(tuple, args) * kwds.get('repeat', 1)
    return tuple(random.choice(pool) for pool in pools)

The function signature would seem to be more readable written with the "repeat" argument specified explicitly, e.g.

def random_product(*args, repeat=1)

But I'm guessing there is a reason why it is written using the general idiom. Can anyone explain?

closed as off-topic by amon, Kilian Foth, Bart van Ingen Schenau, 9000, gnat Dec 15 '14 at 19:54

  • This question does not appear to be about software engineering within the scope defined in the help center.
If this question can be reworded to fit the rules in the help center, please edit the question.


In Python 2, you cannot put a keyword argument after *args, that's a syntax error:

>>> import sys
>>> sys.version_info
sys.version_info(major=2, minor=7, micro=8, releaselevel='final', serial=0)
>>> def random_product(*args, repeat=1):
  File "<stdin>", line 1
    def random_product(*args, repeat=1):
SyntaxError: invalid syntax

If you put it before the positional catch-all, then it captures the first positional argument:

>>> def random_product(repeat=1, *args): return repeat, args
>>> random_product('foo', 'bar')
('foo', ('bar',))

In Python 2 then, your only option is to capture arbitrary keyword arguments with **kw (since that only ever captures actual keyword arguments, not positional arguments), and extract repeat from that.

Python 3 adjusted what is supported; there any keyword arguments specified after the *args catch-all are allowed and are seen as keyword-only:

>>> import sys
>>> sys.version_info
sys.version_info(major=3, minor=4, micro=1, releaselevel='final', serial=0)
>>> def random_product(*args, repeat=1):  return args, repeat
>>> random_product('foo', 'bar')
(('foo', 'bar'), 1)

Not the answer you're looking for? Browse other questions tagged or ask your own question.