[Python-Dev] PEP 3102: Keyword-only arguments
Jean-Paul Calderone
exarkun at divmod.com
Fri May 5 16:01:23 CEST 2006
On Fri, 5 May 2006 08:20:02 -0500, Michael Urman <murman at gmail.com> wrote:
>On 5/5/06, Terry Reedy <tjreedy at udel.edu> wrote:
>> At present, Python allows this as a choice.
>
>Not always - take a look from another perspective:
>
>def make_person(**kwds):
> name = kwds.pop('name', None)
> age = kwds.pop('age', None)
> phone = kwds.pop('phone', None)
> location = kwds.pop('location', None)
> ...
>
>This already requires the caller to use keywords, but results in
>horrid introspection based documentation. You know it takes some
>keywords, but you have no clue what keywords they are. It's as bad as
>calling help() on many of the C functions in the python stdlib.
>
>So what allowing named keyword-only arguments does for us is allows us
>to document this case. That is an absolute win.
Here you go:
import inspect
@decorator
def keyword(f):
def g(*a, **kw):
if a:
raise TypeError("Arguments must be passed by keyword")
args = []
expectedArgs = inspect.getargspec(f)[0]
defaults = inspect.getargspec(f)[-1]
for i, a in enumerate(expectedArgs):
if a in kw:
args.append(kw[a])
elif i >= len(expectedArgs) - len(defaults):
args.append(defaults[i - len(expectedArgs)])
else:
raise TypeError("Missing argument for " + a)
return f(*args)
return g
@keyword
def foo(a, b, c=10, d=20, e=30):
return a, b, c, d, e
try:
foo()
except TypeError:
pass
else:
assert False, "Should have raised TypeError"
try:
foo(1)
except TypeError:
pass
else:
assert False, "Should have raised TypeError"
try:
foo(a=1)
except TypeError:
pass
else:
assert False, "Should have raised TypeError"
assert foo(a=1, b=2) == (1, 2, 10, 20, 30)
assert foo(a=1, b=2, c=3) == (1, 2, 3, 20, 30)
assert foo(a=1, b=2, d=4) == (1, 2, 10, 4, 30)
assert foo(a=1, b=2, c=3, d=4, e=5) == (1, 2, 3, 4, 5)
print 'Success!'
More information about the Python-Dev
mailing list