Reputation: 1069
I'm trying to do something opposite to what **kwargs do and I'm not sure if it is even possible. But knowing Python it probably is :-). I want to have all attributes clearly designed in my method (for auto completion, and ease of use) and I want to grab them all as, lets say a dictionary, and pass them on further.
class Foo(object):
def __init__(self, a=1, b=2):
inputs = grab_function_inputs_somehow()
self.bar(**inputs)
def bar(self, *args, **kwargs):
pass
The normal thing to do is to assign each input into an object parameter but I don't want to do that for all classes. I was hoping for a way to wrap it to a method that can be inherited.
Upvotes: 5
Views: 1939
Reputation: 238229
You can create the dict with variables using locals(). For example:
class Foo(object):
def __init__(self, a=1, b=2):
inputs = locals()
del inputs['self'] # remove self variable
print(inputs)
f = Foo()
Results in print out:
{'b': 2, 'a': 1}
Upvotes: 8
Reputation: 30210
It's possible, but requires a little tweak to your code:
class Foo(object):
def __init__(self, **inputs):
# Have to set your defaults in here
inputs['a'] = inputs.get('a', 1)
inputs['b'] = inputs.get('b', 2)
# Now the rest of your code, as you expected
self.bar(**inputs)
def bar(self, *args, **kwargs):
print("bar got: %s" % kwargs)
# No arguments, use defaults
Foo() # bar got: {'a': 1, 'b': 2}
# Arguments provided
Foo(a=3, b=4) # bar got: {'a': 3, 'b': 4}
So, instead of providing default arguments in the function definition, you're ensuring that the keys you expect exist, either with the provided argument, or with the defaults you pass as the second argument to <dict>.get()
.
Edit __init__
could also be written as:
def __init__(self, **inputs):
# Have to set your defaults in here
if 'a' not in inputs: inputs['a'] = 1
if 'b' not in inputs: inputs['b'] = 2
# Now the rest of your code, as you expected
self.bar(**inputs)
# or
def __init__(self, **inputs):
# Have to set your defaults in here
args = {'a': 1, 'b':2}
args.update(inputs)
# Now the rest of your code, as you expected
self.bar(**args)
Depending on the number of default arguments you have, the last option may be preferred.
Upvotes: -1