[issue18313] In itertools recipes repeatfunc() defines a non-keyword argument as keyword
New submission from py.user: http://docs.python.org/3/library/itertools.html#itertools-recipes "def repeatfunc(func, times=None, *args):"
repeatfunc(lambda x: x, times=None, 1) File "<stdin>", line 1 SyntaxError: non-keyword arg after keyword arg
repeatfunc(lambda x: x, 1, times=None) Traceback (most recent call last): File "<stdin>", line 1, in <module> TypeError: repeatfunc() got multiple values for argument 'times'
---------- assignee: docs@python components: Documentation messages: 191930 nosy: docs@python, py.user priority: normal severity: normal status: open title: In itertools recipes repeatfunc() defines a non-keyword argument as keyword type: enhancement versions: Python 3.3, Python 3.4 _______________________________________ Python tracker <report@bugs.python.org> <http://bugs.python.org/issue18313> _______________________________________
Changes by Ned Deily <nad@acm.org>: ---------- nosy: +rhettinger _______________________________________ Python tracker <report@bugs.python.org> <http://bugs.python.org/issue18313> _______________________________________
Eric V. Smith added the comment: I'm not sure what you're saying. Given the function definition, the way you're calling it is incorrect, and the error messages explain why. Are you saying that these ways to call repeatfunc() are documented somewhere that needs fixing? I couldn't find that on the itertools documentation. ---------- nosy: +eric.smith _______________________________________ Python tracker <report@bugs.python.org> <http://bugs.python.org/issue18313> _______________________________________
Changes by Eric V. Smith <eric@trueblade.com>: ---------- status: open -> pending _______________________________________ Python tracker <report@bugs.python.org> <http://bugs.python.org/issue18313> _______________________________________
py.user added the comment: it should be: "def repeatfunc(func, times, *args):" and None for times described in the docstring ---------- status: pending -> open _______________________________________ Python tracker <report@bugs.python.org> <http://bugs.python.org/issue18313> _______________________________________
Changes by py.user <bugzilla-mail-box@yandex.ru>: ---------- status: open -> pending _______________________________________ Python tracker <report@bugs.python.org> <http://bugs.python.org/issue18313> _______________________________________
Eric V. Smith added the comment: I see. You can't call repeatfunc() and specify times with a named argument because of *args. Interesting. I'll let Raymond weigh in. ---------- status: pending -> open _______________________________________ Python tracker <report@bugs.python.org> <http://bugs.python.org/issue18313> _______________________________________
Ezio Melotti added the comment:
it should be: "def repeatfunc(func, times, *args):" and None for times described in the docstring
This would require you to provide at least two elements, whereas now it's possible to pass just the function (e.g. repeatfunc(random.random)). The problem with the current signature is that you are "forced" to specify the "times" (positionally) whenever you want to pass args to the function -- even if you want an endless repetition (i.e. times=None). ---------- nosy: +ezio.melotti _______________________________________ Python tracker <report@bugs.python.org> <http://bugs.python.org/issue18313> _______________________________________
py.user added the comment:
This would require you to provide at least two elements I see how about "def repeatfunc(func, *args, times=None):" ?
from itertools import starmap, repeat
def repeatfunc(func, *args, times=None): ... """Repeat calls to func with specified arguments. ... ... Example: repeatfunc(random.random) ... """ ... if times is None: ... return starmap(func, repeat(args)) ... return starmap(func, repeat(args, times)) ... def f(*args): ... print(args) ... r = repeatfunc(f, 1, 2) next(r) (1, 2) next(r) (1, 2) next(r) (1, 2) r = repeatfunc(f, 1, 2, times=1) next(r) (1, 2) next(r) Traceback (most recent call last): File "<stdin>", line 1, in <module> StopIteration
---------- _______________________________________ Python tracker <report@bugs.python.org> <http://bugs.python.org/issue18313> _______________________________________
Changes by Raymond Hettinger <raymond.hettinger@gmail.com>: ---------- assignee: docs@python -> rhettinger _______________________________________ Python tracker <report@bugs.python.org> <http://bugs.python.org/issue18313> _______________________________________
Raymond Hettinger added the comment: All of the proposed variants have their own issues. For example, the keyword-argument variant behaves badly if the user leaves off the keyword:
list(repeatfunc(ord, 'A', times=3)) [65, 65, 65] list(repeatfunc(ord, 'A', 3)) Traceback (most recent call last): File "<pyshell#12>", line 1, in <module> list(repeatfunc(ord, 'A', 3)) TypeError: ord() takes exactly one argument (2 given)
I prefer to leave the recipe as is. The primary purpose of the recipe is to illustrate how starmap() and repeat() can be used together. Will that knowledge, a user can easily cobble together in-line code for either the finite version or the infinite iterable version. ---------- priority: normal -> low resolution: -> rejected status: open -> closed _______________________________________ Python tracker <report@bugs.python.org> <http://bugs.python.org/issue18313> _______________________________________
participants (5)
-
Eric V. Smith
-
Ezio Melotti
-
Ned Deily
-
py.user
-
Raymond Hettinger