2

I want to do something like the following.

I want to define a function func(), as:

def func(**kwargs):
    if 'a' in kwargs:
        a = funcA()
    if 'b' in kwargs:
        b = funcB()
    ...

or

def func(**kwargs):
    if 'a' in kwargs:
        kwargs['a'] = funcA()
    if 'b' in kwargs:
        kwargs['b'] = funcB()
    ...

where funcA() and funcB() are defined elsewhere. I want to then call the function func() with a variable number of arguments:

>>> func(a = x)
>>> func(b = y)
>>> func(a = x, b = y)
...

These calls should assign values to x, y, etc. What is the best way to accomplish this?

5
  • I'm not sure what a = funcA(a) would allow you to do, but func(funcA) allows you to pass in function references as parameters. Commented May 2, 2016 at 23:47
  • "These calls should assign values to a, b, etc." - calling a function will not cause assignments to variables in the caller's scope. Also, those example calls are passing a and b positionally, so func wouldn't be able to tell which one is intended as a and which one is intended as b. Python's execution model doesn't work the way you're expecting. You'll need to get used to return values and the parameter passing mechanics. Commented May 2, 2016 at 23:49
  • Assigning to a parameter variable doesn't modify the variable that was used to call the function. Commented May 2, 2016 at 23:49
  • python3 or python2? 3 let's you do keyword-only arguments more easily and expressively. Commented May 2, 2016 at 23:54
  • @RyanHaining I want to do this in Python 2.7. If it can only be done well in Python 3.x, I'd like to hear about that, as well. Commented May 3, 2016 at 0:31

3 Answers 3

3

You can't modify the caller's variable by assigning to the parameter like that, you need to return a value with the return statement, and the caller can assign back to the variable.

def func(**kwargs):
    if 'a' in kwargs and 'b' in kwargs:
        return (funcA(kwargs['a']), funcB(kwargs['b']))
    elseif 'a' in kwargs:
        return funcA(kwargs['a'])
    elseif 'b' in kwargs:
        return funcB(kwargs['b'])

a = func(a = a)
b = func(b = b)
a, b = func(a = a, b = b)

A more general, scalable method would be to return a dictionary.

def func(**kwargs):
    retval = {}
    if 'a' in kwargs:
        retval['a'] = funcA(kwargs['a'])
    if 'b' in kwargs:
        retval['b'] = funcB(kwargs['b'])
    return retval

a = func(a = a)['a']
b = func(b = b)['b']
vals = func(a = a, b = b)
a = vals['a']
b = vals['b']
Sign up to request clarification or add additional context in comments.

2 Comments

This is something like what I had in mind, but I want to avoid enumerating all the possible return combinations. Is there a way around that? I edited my question to hopefully be a little clearer about what I'm trying to do.
A more scalable method would be to return a dictionary.
1

As a general approach, for refusing of writing multiple if condition you better to create a dictionary of your arguments with their relative functions then class the relative function if the intended argument has been passed to the function caller:

def func(**kwargs):
    arg_dict = {'a': funcA, 'b': funcB}
    for arg, value in kwargs.items():
        try:
            yield arg_dict.get(arg)(value)
        except TypeError:
            # do stuff or just pass

This function will return a generator contain the values of relative functions for arguments.

Note that if you don't want to pass the value of your arguments instead of the aforementioned arg_dict you should use arg_dict = {'a': funcA(), 'b': funcB()} and just yield the arg_dict.get(arg).

Comments

0

You're using positional arguments when calling func, which do not pass in **kwargs.

Instead, you have to specify keyword arguments to func too.

Like this:

def func(**kwargs):
    if 'a' in kwargs:
        funcA(kwargs['a'])
    if 'b' in kwargs:
        funB(kwargs['b'])

And then:

func(a='hello')
func(b='thing')
func(a='hello', b='thing')

See the docs for positional and keyword arguments.

Comments

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.