Question: Suppose I have a class with a constructor (or other function) that takes a variable number of arguments and then sets them as class attributes conditionally.

I could set them manually, but it seems that variable parameters are common enough in python that there should be a common idiom for doing this. But I'm not sure how to do this dynamically.

I have an example using eval, but that's hardly safe. I want to know the proper way to do this -- maybe with lambda?

```
class Foo:
    def setAllManually(self, a=None, b=None, c=None):
        if a!=None: 
            self.a = a
        if b!=None:
            self.b = b
        if c!=None:
            self.c = c
    def setAllWithEval(self, **kwargs):
        for key in **kwargs:
            if kwargs[param] != None
                eval("self." + key + "=" + kwargs[param])

```

Answer: 
You can use the [`setattr()`](https://docs.python.org/3/library/functions.html#setattr) method:

```
class Foo:
  def setAllWithKwArgs(self, **kwargs):
    for key, value in kwargs.items():
      setattr(self, key, value)

```

There is an analogous [`getattr()`](https://docs.python.org/3/library/functions.html#getattr) method for retrieving attributes.
The following solutions `vars(self).update(kwargs)` or `self.__dict__.update(**kwargs)` are not robust, because the user can enter any dictionary with no error messages. If I need to check that the user insert the following signature ('a1', 'a2', 'a3', 'a4', 'a5') the solution does not work. Moreover, the user should be able to use the object by passing the "positional parameters" or the "kay-value pairs parameters".

So I suggest the following solution by using a metaclass.

```
from inspect import Parameter, Signature

class StructMeta(type):
    def __new__(cls, name, bases, dict):
        clsobj = super().__new__(cls, name, bases, dict)
        sig = cls.make_signature(clsobj._fields)
        setattr(clsobj, '__signature__', sig)
        return clsobj

def make_signature(names):
    return Signature(
        Parameter(v, Parameter.POSITIONAL_OR_KEYWORD) for v in names
    )

class Structure(metaclass = StructMeta):
    _fields = []
    def __init__(self, *args, **kwargs):
        bond = self.__signature__.bind(*args, **kwargs)
        for name, val in bond.arguments.items():
            setattr(self, name, val)

if __name__ == 'main':

   class A(Structure):
      _fields = ['a1', 'a2']

   if __name__ == '__main__':
      a = A(a1 = 1, a2 = 2)
      print(vars(a))

      a = A(**{a1: 1, a2: 2})
      print(vars(a))

```