[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