Python: how to use lambda or partial to bind arguments other than the first positional argument

Viewed 1078

I am having a lot of confusion in trying to use either a lambda or functools.partial to create a new function with bound positional arguments from an existing function.

I want to do something like this (which is not behaving as desired):

def addFunction(self, name, in_function, secondary_args=None, secondary_kwargs=None):

        # Assign the function with optional args based on whether any
        # optional args are not None

        if secondary_args is not None and secondary_kwargs is not None:
            func = lambda x: in_function(x, *secondary_args, **secondary_kwargs)
        elif secondary_args is None and secondary_kwargs is not None:
            func = lambda x: in_function(x, **secondary_kwargs)
        elif secondary_args is not None and secondary_kwargs is None:
            func = lambda x: in_function(x, *secondary_args)
        else:
            func = in_function
        ###

        func.__doc__ = in_function.__doc__
        self[name] = func # <-- This method is a class method for something deriving dict.

I've also tried replacing all of the lambda statements with equivalent functools.partial statements.

The problem is that if I use this function like this:

# Assume some_function takes 3 arguments, a float, a Bool, and a String,
# in that order.

someObject.addFunction("my_f", some_function, secondary_args=[True, "Option_A"])

now when I try to use (just for example) someObject["my_f"](5.0) it reports the first argument is True when I debug it.

It seems like the bindings, either with lambda or with partial simply push in the positional arguments and either only accept your extra positional argument at the end of *args or else just are dropping it (I'm not sure which).

For my application, since lots of functions will be stored in a particular object like this, with varying numbers of optional arguments chosen by a user, it's important that the function I get back, with bound arguments, still accepts the user's argument as the first positional argument, without resorting to forcing all arguments to be key-word arguments.

This seems like it should be simple enough. What am I missing?

2 Answers
Related