Home > Net >  How can I write updating class parameter values more concisely?
How can I write updating class parameter values more concisely?

Time:02-21

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])
  • Related