[Python-ideas] Positional only arguments

Arnaud Delobelle arno at marooned.org.uk
Fri May 18 19:42:13 CEST 2007


On Fri, May 18, 2007 7:35 am, Arnaud Delobelle wrote:
[...]
> def posonly(f):
>     def posf(*args, **kwargs): return f(*args, *kwargs)
>     posf.__name__ = f.__name__
>     return f

I wrote this just before going to work this morning, and of course I
didn't try it or probably even reread it...  So apart from the typos it
doesn't work with **kwargs.  I've got a working version:

def posonly(arg):
    def deco(f, nposargs):
        name = f.__name__
        posargnames = f.func_code.co_varnames[:nposargs]
        def posf(*args, **kwargs):
            for kw in kwargs:
                if kw in posargnames:
                    raise TypeError("%s() arg '%s' is posonly" % (name, kw))
            return f(*args, **kwargs)
        posf.__name__ = name
        return posf
    if isinstance(arg, int):
        return lambda f: deco(f, arg)
    else:
        return deco(arg, arg.func_code.co_argcount)

It works like this:

@posonly
def foo(x, y, z=10, t=100):
    # All arguments are positional only
    # foo(1, 2, 3) -> 106
    # foo(1, y=2) -> TypeError
    # foo(1, t=7) -> TypeError
    return x+y+z+t

@posonly(2)
def bar(x, y=1, z=10, t=100):
    # Only the first two arguments are posonly
    # bar(1, y=2) -> TypeError
    # bar(1, z=0) -> 102

Being a mere python end-user, I don't know if I'm using the func_code
attribute of functions correctly, so this might break in various ways!

-- 
Arnaud





More information about the Python-ideas mailing list