Welcome, guest | Sign In | My Account | Store | Cart

Working with Windows API which usually takes like a zillion for each function can be a little bit frustrating and if I want to only change two in the middle for each call I had to wrap everything into lambda functions which change arguments to the order that I need to use with partial.

So finally I added kinda dangerous decorator which inserts keywords into right position if detected and was about to use it but ctypes functions don't accept keyword arguments :D so just ended up with decorator :)

Python, 29 lines
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
from functools import partial
from inspect import getargspec, ismethod

def keywords_first(f):
    def wrapper(*a, **k):
        a = list(a)
        #for idx, arg in enumerate(f.func_code.co_varnames[:f.func_code.co_argcount], -ismethod(f)):
        for idx, arg in enumerate(getargspec(f).args, -ismethod(f)): # or [0] in 2.5
            if arg in k:
                if idx < len(a):
                    a.insert(idx, k.pop(arg))
                else:
                    break
        return f(*a, **k)
    return wrapper

@keywords_first
def fun(a, b, c=3): return a, b, c

print fun(1, 3, b=2) # normally: TypeError: f() got multiple values for keyword argument 'b'

def fun2(a, b, *args, **kwargs): return a, b, args, kwargs

print partial(keywords_first(fun2), a=1, c=2, b=2)(3, 4, 5, 6, 7) # noramlly: TypeError ...

def kfpartial(fun, *args, **kwargs):
    return partial(keywords_first(fun), *args, **kwargs)
   
print kfpartial(fun2, a=1, b=2)(3, 4, 5, 6, 7, c=3)

I'm not sure if it is all that useful, but makes the code shorter in some situations, especially when you have to pass handler and some default/reserved values around the code. EDIT: added ismethod to handle better methods and skip self argument

2 comments

obernard78+activestate 12 years, 6 months ago  # | flag

Nice. I always wanted to have a "shuffled" partial to apply to functions in operator module but the getargspec function does not work on built-in functions. :(

Nice recipe nonetheless.

Przemyslaw Podczasi (author) 11 years, 11 months ago  # | flag

With build-ins works in pypy. So if you don't have any specific libraries that hasn't been ported yet, you could switch.

Created by Przemyslaw Podczasi on Wed, 26 Oct 2011 (MIT)
Python recipes (4591)
Przemyslaw Podczasi's recipes (4)

Required Modules

  • (none specified)

Other Information and Tasks