Supposons que j'ai une classe avec un constructeur (ou une autre fonction) qui prend un nombre variable d'arguments, puis les définit comme attributs de classe de manière conditionnelle.
Je pourrais les définir manuellement, mais il semble que les paramètres variables sont suffisamment courants en python pour qu'il devrait y avoir un idiome commun pour le faire. Mais je ne sais pas comment procéder de manière dynamique.
J'ai un exemple utilisant eval, mais ce n'est guère sûr. Je veux savoir la bonne façon de faire cela - peut-être avec 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])
pip install attrs
, décorez votre classe avec@attr.s
, et définissez les arguments commea = attr.ib(); b = attr.ib()
etc. Pour en savoir plus, cliquez ici .Réponses:
Vous pouvez mettre à jour l'
__dict__
attribut (qui représente les attributs de classe sous la forme d'un dictionnaire) avec les arguments de mot-clé:Ensuite vous pouvez:
et avec quelque chose comme:
vous pouvez filtrer les clés au préalable (utilisez
iteritems
plutôt queitems
si vous utilisez toujours Python 2.x).la source
self.__dict__.update(locals())
pour copier également des arguments de position.kwargs[0]
au lieu de justekwargs
? Peutkwargs
même avoir une clé entière? Je suis presque sûr qu'ils doivent être des cordes.Vous pouvez utiliser la
setattr()
méthode:Il existe une
getattr()
méthode analogue pour récupérer les attributs.la source
.getattr()
? Ou pouvez-vous accéder aux attributs avecFoo.key
?Foo.attrname
. Je pense que je voulais simplement souligner le fait que lagetattr
méthode existe. Il est également utile si vous souhaitez fournir une valeur par défaut lorsque l'attribut nommé n'est pas disponible.La plupart des réponses ici ne couvrent pas un bon moyen d'initialiser tous les attributs autorisés à une seule valeur par défaut. Donc, pour ajouter aux réponses données par @fqxp et @mmj :
la source
False
. Bon point!Je propose une variante de la réponse de fqxp , qui, en plus des attributs autorisés , vous permet de définir des valeurs par défaut pour les attributs:
Il s'agit du code Python 3.x, pour Python 2.x vous avez besoin d'au moins un ajustement,
iteritems()
à la place deitems()
.la source
Encore une autre variante basée sur les excellentes réponses de mmj et fqxp . Et si on veut
Par «directement», je veux dire éviter un
default_attributes
dictionnaire superflu .Pas une avancée majeure, mais peut-être utile à quelqu'un ...
EDIT: Si notre classe utilise des
@property
décorateurs pour encapsuler des attributs "protégés" avec des getters et des setters, et si nous voulons pouvoir définir ces propriétés avec notre constructeur, nous pouvons vouloir étendre laallowed_keys
liste avec les valeurs dedir(self)
, comme suit:Le code ci-dessus exclut
dir()
(exclusion basée sur la présence de "__"), etdir()
dont le nom n'est pas trouvé à la fin d'un nom d'attribut (protégé ou non) de__dict__.keys()
, conservant ainsi probablement uniquement les méthodes décorées @property.Cette modification n'est probablement valable que pour Python 3 et supérieur.
la source
J'ai appelé la classe
SymbolDict
parce qu'il s'agit essentiellement d'un dictionnaire qui fonctionne en utilisant des symboles au lieu de chaînes. En d'autres termes, vous faitesx.foo
au lieu dex['foo']
mais sous les couvertures, c'est vraiment la même chose qui se passe.la source
Les solutions suivantes
vars(self).update(kwargs)
ouself.__dict__.update(**kwargs)
ne sont pas robustes, car l'utilisateur peut saisir n'importe quel dictionnaire sans message d'erreur. Si je dois vérifier que l'utilisateur insère la signature suivante («a1», «a2», «a3», «a4», «a5»), la solution ne fonctionne pas. De plus, l'utilisateur doit pouvoir utiliser l'objet en passant les "paramètres positionnels" ou les "paramètres de paires valeur kay".Je suggère donc la solution suivante en utilisant une métaclasse.
la source
Leur solution est peut-être meilleure, mais ce qui me vient à l'esprit est:
la source
celui-ci est le plus simple via larsks
mon exemple:
la source
kwargs
est un dictionnaire d'arguments de mots clés etitems()
est une méthode qui renvoie une copie de la liste de(key, value)
paires du dictionnaire .Je soupçonne qu'il pourrait être préférable dans la plupart des cas d'utiliser des arguments nommés (pour un meilleur code d'auto-documentation) afin que cela puisse ressembler à ceci:
la source
for key, value in (a, b, c)