3

I'm writing a function whose inner logic needs to know which optional keyword arguments the function was called with.

I also need to be able to specify default values for keyword arguments.

If an argument was specified in the call, it will behave one way; if that argument was not specified in the call but was instead taken from the default, it will use the default and will behave a different way.

I do have a working solution, but am wondering if there is a cleaner, safer, more concise way to accomplish the goal:

import json

def addFeature(*args,**kwargs):
    defaults={
        'p1':1,
        'p2':2,
        'p3':3
    }
    mergedKwargs = defaults | kwargs # start with defaults; overwrite with any specified kwargs items
    print(f'args:{args}')
    print('keyword arguments specified in the call to this function:')
    print(json.dumps(kwargs,indent=3))
    print('mergedKwargs:')
    print(json.dumps(mergedKwargs,indent=3))
    # unpack to local variables
    (p1,p2,p3)=(mergedKwargs[k] for k in ('p1','p2','p3'))
    print(f'local values: p1={p1}  p2={p2}  p3={p3}')

addFeature(1,2,p1=5)
addFeature(3,4,p2=7,p3=9)

running this code:

PS C:\Users\caver\Documents\GitHub> python argsTest.py
call to addFeature: args: (1, 2)
keyword arguments specified in the call to this function:
{
   "p1": 5
}
mergedKwargs:
{
   "p1": 5,
   "p2": 2,
   "p3": 3
}
local values: p1=5  p2=2  p3=3

call to addFeature: args: (3, 4)
keyword arguments specified in the call to this function:
{
   "p2": 7,
   "p3": 9
}
mergedKwargs:
{
   "p1": 1,
   "p2": 7,
   "p3": 9
}
local values: p1=1  p2=7  p3=9

PS C:\Users\caver\Documents\GitHub>

One drawback of this method is that the function signature (list of possible arguments) is unknown when using *args and **kwargs.

9
  • 1
    I don't know if it would be more readable but you could set with None like addFeature(..., p1=None,...) and later remeber what variables was different than None, and later replace None with default value (p1 = 1). This can be longer, but you may have signature (of couse problem is that this signature will have None as default value) Commented Nov 1 at 19:57
  • 1
    Possibly XY problem? I'd argue that branching not on values but on where the values come from is ill-advised. If you want defaults, use defaults. If you want different functions, write different functions. You may be able to use polymorphism to your advantage. A 1 is a 1, behaving differently depending on who passed a 1 is a road that leads into debugging hell. Commented Nov 1 at 22:17
  • @Friedrich - possibly so. I posted a new question that is one level higher than this question: stackoverflow.com/questions/79806886 - I know addOrUpdate functions do exist (as opposed to having one add function and one update function) and it would be very nice to be able to make one for this case. Commented Nov 2 at 0:16
  • 1
    @furas - interesting point, so basically it seems like we can set the default values to just be something that will never be equal to a desired value for that parameter. Related to this proposed answer in the 'parent' question: stackoverflow.com/a/79806891/3577105 Commented Nov 2 at 14:58
  • 1
    Before posting on Code Review please read A guide to Code Review for Stack Overflow users and How do I ask a good question? first. Commented Nov 3 at 16:18

0

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.