Reputation: 25
I searched quite a bit for this, so please forgive if I missed something.
I generally desire that methods in my system have only explicit named arguments (other than self of course), like so:
# want an explicit parameter signature
def method_1(self, *, x = None, y = None):
. . .
# and here i want to pass x and/or y if they are not None
possible_args = { }
if x is not None:
possible_args['x'] = x
if y is not None:
possible_args['y'] = y
self.method_2(**possible_args)
# want an explicit parameter signature
def method_2(self, *, x = 1, y = None):
. . .
unfortunately, the values of x and/or y do not get mapped into the named args in method_2, but if i do this instead at the end of method_1:
self.method_2(x = x, y = y)
then the default values of x and y from method_1 override the default values as expressed in the method_2 signature.
what I want is a way, without vaguifying method signatures by accepting an entirely open and unspecified **kwargs, to map whatever might be specified in the call dict into explicit named parameters and not override the defaults for other args that are not in the passed dict.
is this possible?
this is for a system of hundreds of classes, and their interfaces need to be very well specified, else this way lies madness. that is why i do not want to be passing **kwargs around except in a very controlled manner, and I also want to take advantage of named arguments having defaults specified in the method signature. otherwise, i could deal with defaults within the method body, of course:
if x is None:
x = 5
that's just not as nice...
Upvotes: 0
Views: 1179
Reputation: 712
So I gave it a whirl, because I was lost as to what the problem was. I am still lost, but at least now I can show you an MCVE for it:
#! /usr/bin/env python3
'''
A quick **kwargs demo
'''
def method_1(*, x_val=None, y_val=None):
'''
A demonstration with kwargs, that calls another with **kwargs.
'''
possible_args = {}
if x_val is not None:
possible_args['x_val'] = x_val
if y_val is not None:
possible_args['y_val'] = y_val
method_2(**possible_args)
def method_2(*, x_val=1, y_val='y_from_2'):
'''
Print things for the demo.
'''
print('x_val = ', x_val, ', y_val = ', y_val)
method_1(x_val=17, y_val=7)
method_1(x_val=13)
method_1(y_val=5)
method_1()
Produces the output:
x_val = 17 , y_val = 7
x_val = 13 , y_val = y_from_2
x_val = 1 , y_val = 5
x_val = 1 , y_val = y_from_2
Which is exactly what one should expect.
Upvotes: 1