Je propose une variante de Réponse de fqxp qui, en plus de attributs autorisés permet de définir valeurs par défaut pour les attributs :
class Foo():
def __init__(self, **kwargs):
# define default attributes
default_attr = dict(a=0, b=None, c=True)
# define (additional) allowed attributes with no default value
more_allowed_attr = ['d','e','f']
allowed_attr = list(default_attr.keys()) + more_allowed_attr
default_attr.update(kwargs)
self.__dict__.update((k,v) for k,v in default_attr.items() if k in allowed_attr)
Il s'agit de code Python 3.x, pour Python 2.x vous avez besoin d'au moins un ajustement, iteritems()
à la place de items()
.
SUIVI TRÈS TARDIF
J'ai récemment réécrit le code ci-dessus sous la forme d'un fichier décorateur de classe afin de réduire au minimum le codage des attributs. D'une certaine manière, il ressemble à certaines caractéristiques de la les @dataclass
décorateur et c'est ce que vous pourriez vouloir utiliser à la place.
# class decorator definition
def classattributes(default_attr,more_allowed_attr):
def class_decorator(cls):
def new_init(self,*args,**kwargs):
allowed_attr = list(default_attr.keys()) + more_allowed_attr
default_attr.update(kwargs)
self.__dict__.update((k,v) for k,v in default_attr.items() if k in allowed_attr)
cls.__init__ = new_init
return cls
return class_decorator
# usage:
# 1st arg is a dict of attributes with default values
# 2nd arg is a list of additional allowed attributes which may be instantiated or not
@classattributes( dict(a=0, b=None, c=True) , ['d','e','f'] )
class Foo():
pass # add here class body except __init__
@classattributes( dict(g=0, h=None, j=True) , ['k','m','n'] )
class Bar():
pass # add here class body except __init__
obj1 = Foo(d=999,c=False)
obj2 = Bar(h=-999,k="Hello")
obj1.__dict__ # {'a': 0, 'b': None, 'c': False, 'd': 999}
obj2.__dict__ # {'g': 0, 'h': -999, 'j': True, 'k': 'Hello'}