Requiring arguments to be passed as keyword arguments
Michael Haggerty
mhagger at blizzard.harvard.edu
Tue Oct 5 01:52:02 EDT 1999
Hi,
Sometimes I would like to write functions with arguments that are
REQUIRED to be passed as keyword arguments rather than positional
arguments. For example, for the following function I might want the
second parameter to be passed as a keyword parameter:
f(1, 2) # Exception
f(1, variation=2) # OK
It is possible, though cumbersome, to enforce this requirement with
python by the use of **arguments:
def f(x, **keyw):
variation = keyw['variation'] # might throw confusing exception
# test that no unwanted keyword arguments were passed:
del keyw['variation']
assert not keyw
# ...
The more keyword arguments, the nastier (and these cases usually occur
when there are a large number of multiple keyword arguments). It is
even less convenient if you want to supply default arguments. I hope
you will all agree that it is unpleasant to have to resort to
*arguments or **arguments.
Why do I want to require keyword arguments? Because I don't want the
order of the arguments to be part of the advertised interface to my
function. The arguments may have no sensible ordering (for example, a
group of boolean options for which the defaults are usually used) and
thus their use as positional arguments would always be confusing. Or
I might want to allow an indeterminate number of positional arguments,
followed by keyword arguments.
[Actually this idea arose from a real situation. I wrote a function
with a bunch of arguments, which I intended to be passed as keyword
arguments. A colleague called it with a bunch of positional
arguments. Later I inserted more arguments, changing their order and
not thinking anything of it. But suddenly my colleagues' code failed
in a non-obvious way.]
Could there be a more convenient way to enforce the keyword-argument
requirement? Perhaps the rule that no named arguments may follow a
*argument (an asterisk argument, i.e., returning a list of all unused
positional arguments) could be replaced with the proviso that any
named arguments following a *argument MUST be passed as keyword
arguments. Moreover, a `*' with no dummy variable name could be put
in a function signature to indicate that no more positional arguments
are allowed AND that all following arguments must be keyword
arguments:
def f(x, *, variation):
# same effect as above
Then keyword arguments could also easily be combined with
indeterminate numbers of positional arguments:
def g(*x, color='red'):
print x
print color
>>> g(1,2,3)
(1, 2, 3)
red
>>> g(4,5,6, color='blue')
(4, 5, 6)
blue
(Without this change g() would have to be written with a **keyw
argument.) This change would not break any existing code because it
is currently not allowed to include named arguments following an
*argument.
Maybe this is overkill for a feature of limited utility. But I think
the occasional need to muck about with *arg and **keyw arguments is
one of the few tedious tasks in Python. Similar to the new extended
calling syntax, this change would make that need rarer.
Reactions?
Michael
--
Michael Haggerty
mhagger at blizzard.harvard.edu
More information about the Python-list
mailing list