The following solutions vars(self).update(kwargs) or self.__dict__.update(**kwargs) are not reliable, as the user can enter any dictionary without error messages. If I need to check that the user inserts the following signature ('a1', 'a2', 'a3', 'a4', 'a5'), the solution does not work. In addition, the user should be able to use the object by passing "positional parameters" or "parameters of kay-value pairs".
Therefore, I propose the following solution 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))
antonjs Nov 26 '18 at 12:57 2018-11-26 12:57
source share