How to avoid repetitive code when defining a new type in python with signature verification

Viewed 90

I wonder if there is a better solution to define a new type in python.

I am writing the init method of a new class in this way:

class MyType (Base):

  def __init__(self, **kwargs):
    self.a1 = kwargs['a1']
    self.a2 = kwargs['a2']
    self.a3 = kwargs['a3']

but I would like to write a compact coding style like that:

class MyType (Base):

   __fields__ = ['a1', 'a2', 'a3']

The following solution vars(self).update(kwargs) or self.__dict__.update(**kwargs) does not satisfied me, because the user can enter any dictionary with no error messages. I need to check that the user insert the following signature ('a1', 'a2', 'a3', 'a4', 'a5'). Moreover, the user should be able to use the object by passing the "positional parameters" or the "kay-value pairs parameters".

I implemented the following code which is able to spot KeyError when some parameter is missing. but when extra argument is added I do not get any error:

class Structure:
    _fields = []
    def __init__(self, *args, **kwargs):
        print(self._fields, kwargs)
        for name in self._fields:
            setattr(self, name, kwargs[name])

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

if __name__ == '__main__':
    m = MyType(**{'a1': 1}) # KeyError: 'a2'
    print(vars(m))      
    m = MyType(**{'a1': 1, 'a2': 3, 'a3': 4, 'a4': 5}) # no KeyError!!
    print(vars(m))

Thanks, Frederick

2 Answers

Have a look at python3.7 data classes.

Quote from there:

@dataclass
class InventoryItem:
    '''Class for keeping track of an item in inventory.'''
    name: str
    unit_price: float
    quantity_on_hand: int = 0

Will add, among other things, a __init__() that looks like:

def __init__(self, name: str, unit_price: float, quantity_on_hand: int=0):
    self.name = name
    self.unit_price = unit_price
    self.quantity_on_hand = quantity_on_hand

You can just update the instance dict in __init__.

>>> class MyType:
...:    def __init__(self, **kwargs):
...:        vars(self).update(kwargs)
...:        
>>> m = MyType(a1=1, a2=2, a3=3)
>>> vars(m)
>>> {'a1': 1, 'a2': 2, 'a3': 3}
>>> m.a1, m.a2, m.a3
>>> (1, 2, 3)
Related