Simple question; any ideas how to write this more concisely? I have a class with these (already initialised) parameters that I would like to have the option for to update.
def update_parameters(self, a=None, g=None, n=None, d=None, s=None, K=None, A=None, L=None):
# If the argument is not none, change the parameter value of the class
if a:
self.a = a
if g:
self.g = g
if n:
self.n = n
if d:
self.d = d
if s:
self.s = s
if K:
self.K = K
if A:
self.A = A
if L:
self.L = L
CodePudding user response:
You could just use **args
instead of explicitly defining all of those parameters. You could then use setattr()
to update any valid ones.
For example:
class Test():
def __init__(self):
self.a = None
self.g = None
self.n = None
def update_parameters(self, **args):
for arg, value in args.items():
if hasattr(self, arg) and value is not None:
setattr(self, arg, value)
def __str__(self):
return f"{self.a}, {self.g}, {self.n}"
t = Test()
t.update_parameters(a=21, z='rubbish', n=100)
t.update_parameters(a=42, n=None)
print(t)
This shows a
and n
being updated and z
being ignored:
42, None, 100
Obviously you need to extend it to all of your parameters.
FYI:
setattr(x, 'foobar', 123)
is equivalent to x.foobar = 123
CodePudding user response:
You can use **kwargs
and force the users to only pass keyword argument. Then it's easy to iterate over them and use setattr()
:
class A:
def update_parameters(self, **kwargs):
for k, v in kwargs.items():
if v is not None:
setattr(self, k, v)
but this has a problem, Any not-none values are going to be added to the instance's dictionary. So maybe you can add another check to see if the k
is valid.
class A:
def update_parameters(self, **kwargs):
for k, v in kwargs.items():
if k in valid_attrs and v is not None:
setattr(self, k, v)
Or even use the instance's __dict__
:
def update_parameters(self, **kwargs):
for k, v in kwargs.items():
if k in self.__dict__ and v is not None:
setattr(self, k, v)
Here is the complete code:
class A:
def __init__(self, a, b, c):
self.a = a
self.b = b
self.c = c
def update_parameters(self, **kwargs):
for k, v in kwargs.items():
if k in self.__dict__ and v is not None:
setattr(self, k, v)
def __repr__(self):
return f"A(a={self.a}, b={self.b}, c={self.c})"
obj = A(10, 20, 30)
print(obj)
obj.update_parameters(b=40, c=50, d=60)
print(obj)
output:
A(a=10, b=20, c=30)
A(a=10, b=40, c=50)
This ignores the d=60
value. If you want you can raise exception.
CodePudding user response:
How about making a seperate method that checks for None?
def UpdateIfNotNone(To, From):
if From is not None:
To = From
Then the original method can be like
def update_parameters(self, a=None, g=None, ...):
worklist = [(self.a,a), (self.g, g) ...]
for task in worklist:
UpdateIfNotNone(task[0], task[1])