0

I have already found various answers to this question (eg. lambda function acessing outside variable) and all point to the same hack, namely (eg.) lambda n=i : n*2 with i a variable in the external scope of lambda (hoping I'm not misusing the term scope). However, this is not working and given that all answers I found are generally from couple of years ago, I thought that maybe this has been deprecated and only worked with older versions of python. Does anybody have an idea or suggestion on how to solve this?

SORRY, forgot the MWE

from inspect import getargspec
params = ['a','b']
def test(*args):
    return args[0]*args[1] 

func = lambda p=params : test(p)

I expected the signature of func to be ['a','b'] but if I try

func(3,2)

I get a Type error (TypeError: <lambda>() takes at most 1 argument (2 given) )

and it's true signature (from getargspec(func)[0] ) is ['p']

In my real code the thing is more complicated. Shortly:

def fit(self, **kwargs):
        settings = self.synch()
        freepars = self.loglike.get_args()
        func = lambda p=freeparams : self.loglike(p)
        minuit = Minuit(func,**settings)

I need lambda because it's the only way I could think to create inplace a function object depending on a non-hardcoded list of variables (extracted via a method get_params() of the instance self.loglike). So func has to have the correct signature, to match the info inside the dict settings

The inspector gives ['p'] as argument of func, not the list of parameters which should go in loglike. Hope you can easily spot my mistake. Thank you

11
  • The behavior hasn't changed. You have a bug. Commented Nov 28, 2016 at 17:25
  • Could you post your code? Commented Nov 28, 2016 at 17:27
  • 1
    Can you post a MCVE that demonstrates the problem? The late binding behavior of lambdas hasn't changed (nor do I expect it to any time in the future), so it's quite possible that you have a bug that is unrelated to that. Building an MCVE might make it more obvious what the actual problem is in your code. Commented Nov 28, 2016 at 17:28
  • Please expand on "not working". Commented Nov 28, 2016 at 17:37
  • my MWE is quite crappy, but the small explanation of my true code should highlight what I'm trying to do Commented Nov 28, 2016 at 17:56

1 Answer 1

0

There's no way to do exactly what you want. The syntax you're trying to use to set the signature of the function you're creating doesn't do what you want. It instead sets a default value for the argument you've defined. Python's function syntax allows you to define a function that accepts an arbitrary number of arguments, but it doesn't let you define a function with argument names in a variable.

What you can do is accept *args (or **kwargs) and then do some processing on the value to match it up with a list of argument names. Here's an example where I turn positional arguments in a specific order into keyword arguments to be passed on to another function:

arg_names = ['a', 'b']

def foo(*args):
    if len(args) != len(arg_names):
        raise ValueError("wrong number of arguments passed to foo")

    args_by_name = dict(zip(arg_names, args))

    some_other_function(**args_by_name)

This example isn't terribly useful, but you could do more sophisticated processing on the args_by_name dict (e.g. combining it with another dict), which might be relevant to your actual use case.

Sign up to request clarification or add additional context in comments.

1 Comment

Thank you for you answer @Blckknght. Last week I came across the decorator.FunctionMaker class. Its documentation says that the create() method allows to create a function with desired signature. however, the documentation isn't as detailed as Python's standard documentations, so I was able to create a function of the desired signature, but it returned a None. Any thoughts on this?

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.