Python: Passing parameters by name along with kwargs
Asked Answered
H

3

40

In python we can do this:

def myFun1(one = '1', two = '2'):
    ...

Then we can call the function and pass the arguments by their name:

myFun1(two = 'two', one = 'one')

Also, we can do this:

def myFun2(**kwargs):
    print kwargs.get('one', 'nothing here')

myFun2(one='one')

So I was wondering if it is possible to combine both methods like:

def myFun3(name, lname, **other_info):
    ...

myFun3(lname='Someone', name='myName', city='cityName', otherInfo='blah')

In general what combinations can we do?

Thanks and sorry for my silly question.

Hulbig answered 25/2, 2013 at 19:25 Comment(1)
related: #9873324Bisque
O
47

The general idea is:

def func(arg1, arg2, ..., kwarg1=default, kwarg2=default, ..., *args, **kwargs):
    ...

You can use as many of those as you want. The * and ** will 'soak up' any remaining values not otherwise accounted for.

Positional arguments (provided without defaults) can't be given by keyword, and non-default arguments can't follow default arguments.

Note Python 3 also adds the ability to specify keyword-only arguments by having them after *:

def func(arg1, arg2, *args, kwonlyarg=default):
    ...

You can also use * alone (def func(a1, a2, *, kw=d):) which means that no arguments are captured, but anything after is keyword-only.

So, if you are in 3.x, you could produce the behaviour you want with:

def myFun3(*, name, lname, **other_info):
    ...

Which would allow calling with name and lname as keyword-only.

Note this is an unusual interface, which may be annoying to the user - I would only use it in very specific use cases.

In 2.x, you would need to manually make this by parsing **kwargs.

Officeholder answered 25/2, 2013 at 19:27 Comment(9)
Careful. I don't think you can have default args after *args (at least not on python2.x).Bisque
@Bisque I'm always forgetting 2.x shortcomings, fixed.Officeholder
in python 2.7 def test(var, kwarg1=1, *args, **kwargs): ... doesn't work for me. complains about having multiple values for a keyword argument.Kuster
@Raufio The issue there is you are presumably calling it, filling kwarg1 positionally and by keyword - that clearly provides two values for the same variable. E.g: test(1, 2, kwarg1=3), should kwarg1 be 2 or 3? Either do test(1, 2) or test(1, kwarg1=3).Officeholder
ok, so how do I call test with var = 1, kwarg1 = 10, *args=[1,2,3] and **kwarg = {"test":15}? (using kwarg1 as a keyword)Kuster
@Raufio test(1, 10, 1, 2, 3, test=15)Officeholder
Positional arguments (provided without defaults) can't be given by keyword Actually it's possible at least for Python 2.7. Keyword arguments get assigned to positional by names. "for each keyword argument, the identifier is used to determine the corresponding slot (if the identifier is the same as the first formal parameter name, the first slot is used, and so on)." docs.python.org/2/reference/expressions.html#callsParette
@Parette You can give the names, but you can't give them as keyword arguments - they still have to be in order. They are just named arguments really - and are useful for some things, but not the same.Officeholder
Tuples worked for me. Instead of def test(var, kwarg1=1, *args, **kwargs):..., used def test(var, kwarg1=1, args, **kwargs) and then called test(1, kwarg1=10, (1, 2, 3,), test=15). Of course the tuple is then to be used by index and not names. But for me, I really needed that kwarg=10.Friday
C
3

You can add your named arguments along with kwargs. If the keys are available in the calling function It will taken to your named argument otherwise it will be taken by the kwargs dictionary.

def add(a=1, b=2,**c):
    res = a+b
    for items in c:
        res = res + c[items]
    print(res)
add(2,3)

5

add(b=4, a =3)

7

add(a =1,b=2,c=3,d=4)

10

Cartage answered 25/2, 2020 at 16:40 Comment(0)
P
2

It's possible at least for Python 2.7. Keyword arguments get assigned to positional parameters by name, so you can do

In [34]: def func(name, lname, **kwargs):
    print 'name='+name, 'lname='+lname
    print kwargs
   ....:     

In [35]: func(lname='lname_val', name='name_val', city='cityName', otherInfo='blah')
name=name_val lname=lname_val
{'city': 'cityName', 'otherInfo': 'blah'}

Official docs state it that way: "If keyword arguments are present, they are first converted to positional arguments, as follows. First, a list of unfilled slots is created for the formal parameters. If there are N positional arguments, they are placed in the first N slots. Next, for each keyword argument, the identifier is used to determine the corresponding slot (if the identifier is the same as the first formal parameter name, the first slot is used, and so on). If the slot is already filled, a TypeError exception is raised. Otherwise, the value of the argument is placed in the slot, filling it (even if the expression is None, it fills the slot)." https://docs.python.org/2/reference/expressions.html#calls

Parette answered 14/2, 2018 at 9:59 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.