Cobertos
Cobertos

Reputation: 2253

Wrap callback function to include extra argument when caller verifies exact callback signature

I'm trying to bind multiple callback functions across multiple properties with code that looks something like:

for key in keys:
    def callback(self, value):
        #Do stuff...
        return None

    doSomething(callback)

This works because the calling code (that calls callback) expect exactly two parameters and the callback to return None. The issue is now I want to wrap the callback such that I can also pass the key in something like:

for key in keys:
    def wrappedCallback(self, value):
        #How do I get key in here???
        realCallback(self, key, value)
        return None

    doSomething(wrapperCallback)

But I have no idea how to get key inside of wrapperCallback. I can't add an extra default parameter like:

...
#This throws with "expected a function taking 2 arguments, not 3"
def wrappedCallback(self, value, key=key):
    realCallback(self, key, value)
    ...

because this will throw an error from the caller (it's C code that expects a very strict callback). I've also tried functools.partial but then I get expected a function, not a functools.partial

How do I wrap the passed callback function to include the external parameter key (from the for loop) while keeping the exact signature described?

Upvotes: 0

Views: 1316

Answers (2)

Brett Beatty
Brett Beatty

Reputation: 5963

I would create a callback generator that takes your parameters (such as key) and creates your callbacks.

>>> def callback_generator(key):
...     def callback(self, value):
...         do_something_with(key, value)
...     return callback
...
>>> for key in keys:
...     doSomething(callback_generator(key))
...

Upvotes: 1

Cobertos
Cobertos

Reputation: 2253

Minutes after I figured out that I can create a function inside the for loop to get a new stack frame. This unfortunately does not seem at all Pythonic...

for key in keys:
    def dummyForStackFrame(key): #Extra function to get a new stack frame with key
        def wrappedCallback(self, value):
            realCallback(self, key, value)
            return None
        doSomething(wrappedCallback
    dummyForStackFrame(key)

Upvotes: 0

Related Questions