How can I conditionally set an attribute in the __init__
of a class, from a **kwargs
parameter?
I know that I can do:
default = 1
class foo():
def __init__(self, X=None, Y=None):
self.X = X if X else default
self.Y = Y if Y else default
F = foo()
f = foo(X=2, Y=3)
but I want to make this work with a variable-keyword parameter (**kwargs
), in order to understand them properly.
These attempts did not work:
default = 1
class foo():
def __init__(self, **kwargs):
self.X = default or kwargs['X']
self.Y = default or kwargs['Y']
F = foo()
f = foo(X=2, Y=3)
This way, only the default value is used even if other values are provided. If the order is switched (kwargs['X'] or default
etc.), the code raises a KeyError
if the keyword arguments are not provided.
default = 1
class foo():
def __init__(self, **kwargs):
self.X = value if kwargs["X"] is None else kwargs["X"]
self.Y = value if kwargs["Y"] is None else kwargs["Y"]
F = foo()
f = foo(X=2, Y=3)
This still raises a KeyError
for missing keyword arguments.
class foo():
def __init__(self, **kwargs):
self.X = kwargs.get('X', value) # get() take key_name, default value this opetions
self.Y = kwargs.get('Y', value)
# or use normal params with default value
class foo():
# change dict to any type
def __init__(self, x = None, y = None):
self.X = x or value
self.Y = y or value
# or better use Keyword Argument with default value if you have x y only
class foo():
# change dict to any type
def __init__(self, x: dict = None, y: dict = None):
self.X = x or value
self.Y = y or value
you need also know when should use **kwargs
There are two common cases:
First: You are wrapping another function which takes a number of keyword argument, but you are just going to pass them along:
def my_wrapper(a, b, **kwargs):
do_something_first(a, b)
the_real_function(**kwargs)
Second: You are willing to accept any keyword argument, for example, to set attributes on an object:
class OpenEndedObject:
def __init__(self, **kwargs):
for k, v in kwargs.items():
setattr(self, k, v)
foo = OpenEndedObject(a=1, foo='bar')
assert foo.a == 1
assert foo.foo == 'bar'
read this if you need know more
Why use **kwargs in python? What are some real world advantages over using named arguments?