Quelle est la bonne façon d'utiliser **kwargs
en Python en ce qui concerne les valeurs par défaut?
kwargs
renvoie un dictionnaire, mais quelle est la meilleure façon de définir les valeurs par défaut, ou y en a-t-il un? Dois-je simplement y accéder en tant que dictionnaire? Utiliser la fonction get?
class ExampleClass:
def __init__(self, **kwargs):
self.val = kwargs['val']
self.val2 = kwargs.get('val2')
Une question simple, mais sur laquelle je ne trouve pas de bonnes ressources. Les gens le font de différentes manières dans le code que j'ai vu et il est difficile de savoir quoi utiliser.
__init__()
. Quelqu'un peut-il expliquer pourquoi il s'agit d'une transgression non pelucheuse?self.__dict__update(**kwargs)
peut redéfinir les méthodes et provoquer d'autres bugsAlors que la plupart des réponses disent que, par exemple,
est le même que"
ce n'est pas vrai. Dans ce dernier cas,
f
peut être appelé asf(23, 42)
, tandis que le premier cas accepte uniquement les arguments nommés - pas d'appels de position. Souvent, vous voulez permettre à l'appelant une flexibilité maximale et, par conséquent, la deuxième forme, comme l'affirment la plupart des réponses, est préférable: mais ce n'est pas toujours le cas. Lorsque vous acceptez de nombreux paramètres facultatifs dont généralement seuls quelques-uns sont transmis, il peut être une excellente idée (éviter les accidents et le code illisible sur vos sites d'appels!) De forcer l'utilisation d'arguments nommés - enthreading.Thread
est un exemple. La première forme est de savoir comment implémenter cela dans Python 2.L'idiome est si important qu'en Python 3 il a maintenant une syntaxe de support spéciale: chaque argument après un simple
*
dans ladef
signature est uniquement mot-clé, c'est-à-dire, ne peut pas être passé comme argument positionnel, mais seulement comme argument nommé. Donc, en Python 3, vous pouvez coder ce qui précède comme suit:En effet, dans Python 3, vous pouvez même avoir des arguments de mots clés uniquement qui ne sont pas facultatifs (ceux sans valeur par défaut).
Cependant, Python 2 a encore de longues années de vie productive à venir, il est donc préférable de ne pas oublier les techniques et les idiomes qui vous permettent d'implémenter dans Python 2 des idées de conception importantes qui sont directement prises en charge dans le langage Python 3!
la source
Je suggère quelque chose comme ça
Et puis utilisez les valeurs comme vous le souhaitez
dictionaryA.update(dictionaryB)
ajoute le contenudictionaryB
àdictionaryA
écraser les clés en double.la source
for key in options: self.__setattr__(key, options[key])
et je suis prêt à partir. :)Tu ferais
ou
Si vous utilisez
pop
, vous pouvez vérifier si des valeurs parasites ont été envoyées et prendre les mesures appropriées (le cas échéant).la source
.pop
cela vous aiderait à «vérifier s'il y a des valeurs parasites envoyées»?kwargs
pour une raison.default_value
passée? Et supprime cette clé par la suite?L'utilisation de ** kwargs et des valeurs par défaut est facile. Parfois, cependant, vous ne devriez pas utiliser ** kwargs en premier lieu.
Dans ce cas, nous ne faisons pas vraiment le meilleur usage de ** kwargs.
Ce qui précède est un "pourquoi s'embêter?" déclaration. C'est la même chose que
Lorsque vous utilisez ** kwargs, vous voulez dire qu'un mot clé n'est pas seulement facultatif, mais conditionnel. Il existe des règles plus complexes que de simples valeurs par défaut.
Lorsque vous utilisez ** kwargs, vous voulez généralement dire quelque chose de semblable à ce qui suit, où les valeurs par défaut simples ne s'appliquent pas.
la source
Puisque
**kwargs
est utilisé lorsque le nombre d'arguments est inconnu, pourquoi ne pas le faire?la source
Voici une autre approche:
la source
get_form_kwargs()
). ccbv.co.uk/projects/Django/1.5/django.views.generic.edit/…get_form()
méthode montre comment obtenir des arguments de mots clés de manière extensive en se reportant à une autre méthode (get_form_kwargs
comme mentionné ci-dessus). Il instancie le formulaire comme suit:form_class(**self.get_form_kwargs())
.get_form_kwargs()
dans une vue de sous-classe et d'ajouter / supprimer des kwargs en fonction d'une logique spécifique. Mais c'est pour un tutoriel Django.Je pense que la bonne façon d'utiliser
**kwargs
en Python en ce qui concerne les valeurs par défaut est d'utiliser la méthode du dictionnairesetdefault
, comme indiqué ci-dessous:De cette façon, si un utilisateur passe 'val' ou 'val2' dans le mot-clé
args
, ils seront utilisés; sinon, les valeurs par défaut qui ont été définies seront utilisées.la source
Vous pourriez faire quelque chose comme ça
la source
Faisant suite à @srhegde suggestion d'utiliser setattr :
Cette variante est utile lorsque la classe devrait avoir tous les éléments de notre
acceptable
liste.la source
Si vous souhaitez combiner cela avec * args, vous devez conserver * args et ** kwargs à la fin de la définition.
Donc:
la source
@AbhinavGupta et @Steef ont suggéré d'utiliser
update()
ce que j'ai trouvé très utile pour le traitement de grandes listes d'arguments:Que se passe-t-il si nous voulons vérifier que l'utilisateur n'a transmis aucun argument erroné / non pris en charge? @VinaySajip a souligné qu'il
pop()
peut être utilisé pour traiter de manière itérative la liste des arguments. Ensuite, tous les arguments restants sont faux. Agréable.Voici une autre façon possible de le faire, qui conserve la syntaxe simple d'utilisation
update()
:unknown_args
est unset
contenant les noms des arguments qui n'apparaissent pas dans les valeurs par défaut.la source
Une autre solution simple pour traiter des arguments inconnus ou multiples peut être:
la source
** kwargs donne la liberté d'ajouter n'importe quel nombre d'arguments de mots clés. On peut avoir une liste de clés pour lesquelles il peut définir des valeurs par défaut. Mais la définition de valeurs par défaut pour un nombre indéfini de clés semble inutile. Enfin, il peut être important d'avoir les clés comme attributs d'instance. Donc, je ferais cela comme suit:
la source