2012-01-30 1 views
5

Possible en double:
Python conditional assignment operatorPython équivalent de Perl/Ruby || =

Toutes mes excuses pour une question aussi simple, mais googler ||= est pas très utile;)

Existe-t-il un équivalent en Python à l'instruction ||= présente dans Ruby et Perl?

Par exemple:

foo = "hey" 
foo ||= "what" # assign foo if it's undefined 
# foo is still "hey" 

bar ||= "yeah" 
# bar is "yeah" 

aussi ce qui est le terme général pour quelque chose comme ça? L'affectation conditionnelle était ma première supposition mais le Wikipedia page n'est pas tout à fait ce que j'avais en tête.

+0

Oui c'est un doublon, il semble. Merci Adam! –

+2

'$ foo || =" quoi "' réattribue '$ foo' s'il est déjà * faux *. Bien sûr 'undef' est faux, mais il en est de même de zéro et de la chaîne nulle. Pour réaffecter seulement une valeur indéfinie, utilisez des barres obliques à la place, comme '$ foo // =" quoi "' – Borodin

+0

Notez que '//' (et son extension, '// =') a été ajouté à perl 5.10. Si vous êtes toujours bloqué sur 5.8.x, vous ne pourrez pas utiliser '// =' (et vous devriez envisager sérieusement de mettre à jour si possible). –

Répondre

6

Un peu peu plus bavard, mais le plus simple est

foo = "hey" 
foo = foo or "what" 
#foo is still "hey" 

bar = None 
bar = bar or "yeah" 
#bar is "yeah" 

Vous pouvez également utiliser l'opérateur ternaire

bar = None 
bar = bar if bar else "yeah" 

Cependant, si je vous comprends, ||= attribue des variables qui n'étaient pas défini, sans plainte? Je n'en avais aucune idée.

Pour ce faire dans la portée locale, ce vilain petit canard pourrait travailler

bar = locals()['bar'] if 'bar' in locals() else 'yeah' 

EDIT:

Je viens de voir le double, et il a beaucoup de solutions aussi bien :) Pour ceux qui sont trop paresseux pour regardez, ils comprennent également une variante plus agréable sur mon dernier

foo = foo if 'foo' in locals() else 'hey' 

mais cela ne fonctionnera pas pour les variables non définies, seules les valeurs falsy seront remplacées et non défini soulèvera un NameError. Ce prochain sera, OTOH, ne fonctionne que pour undefined et toujours garder la même valeur falsy pré-existante, qui comme le dit @Borodin est comme //= en Perl

foo = locals().get('foo','hey') 

et, bien sûr, quelqu'un a utilisé une exception :(

.
try: 
    v 
except NameError: 
    v = 'bla bla' 
+0

non, '|| =' réaffectera une variable si elle est 'false'. Voir mon commentaire sur la question. Pourquoi attendez-vous une plainte? – Borodin

+0

Merci pour la réponse, au début je n'ai pas remarqué la différence nuancée. le 'bar = None' est nécessaire pour que cela fonctionne, sinon il lance un' NameError'. Pour un comportement identique, vous avez besoin de votre extrait 'local() ['bar']'. Merci encore :) –

+0

@borodin Je ne suis pas un Rubis, je ne l'ai utilisé que pour des trucs stupides comme Chef. Je voulais juste dire que je ne savais pas que 'undef' dans Ruby était falsey, puisque ce n'est pas le cas en Python (les références non définies jettent des exceptions).Peu importe, merci pour vos commentaires, j'ai appris quelque chose :) –

1

ne suis pas sûr du nom le mieux que je pouvais trouver est:

>>> a = 'foo' 
>>> a = 'a' in locals() and a or 'what' 
>>> a 
'foo' 
>>> b = 'b' in locals() and b or 'yeah' 
>>> b 
'yeah' 
2

vous avez presque jamais des variables non définies en Python, et quand vous faites cela signifie généralement que vous avez m ade une erreur.Cependant, de manière pratique, la plupart des types de valeurs couramment utilisés comme valeurs par défaut (conteneurs vides, chaînes de longueur zéro, zéro et None) sont "falsifiés" en Python, de sorte que vous verrez parfois des choses comme ça qui profite de la façon dont le travail des opérateurs booléens en Python:

name = name or "Guido" # if name is empty, set it to "Guido" 
numb = numb or 42  # if numb is zero, set it to 42 

la raison pour laquelle cela fonctionne est que cesse Python évalue or si le premier argument est « truthy, » qui est appelé court-circuit, et dans les deux cas retourne l'argument réel, plutôt que comme résultat True ou False. Donc, si name est "Jim" alors "Jim" or "Guido" évalue à "Jim" parce que "Jim" est une chaîne de longueur non-zéro et donc "véridique".

Bien sûr, cela ne fonctionne pas très bien lorsque vous ne connaissez pas le type de la valeur que vous traitez et/ou qu'une valeur «falsifiée» est une valeur valide. Cependant, cela fonctionne assez bien avec des choses comme des fichiers de configuration et raw_input() où une valeur manquante renvoie une chaîne vide:

name = raw_input("What is your name? ") or "Guido" 

Un autre idiome commun est utilisé en traitant des éléments dans un dictionnaire. La méthode get() de la classe de dictionnaire vous permet de spécifier une valeur par défaut à utiliser si la variable n'est pas dans le dictionnaire.

name = values.get("name", "Guido") 

Ceci peut être utilisé lorsque votre fonction a été passé arguments mots clés en utilisant la convention **kwargs. Vous pouvez utiliser aussi avec des variables, comme les globals() et locals() fonctions renvoient respectivement, toutes les variables globales ou locales actuellement portée comme un dictionnaire:

name = locals().get("name", "Guido") 

Cependant, comme je l'ai dit, vous aurez rarement Variables en fait indéfinies en Python. Dans des cas comme les frameworks Web, vous passerez des arguments de chaîne de requête en tant que dictionnaire, par exemple, et pourrez utiliser la méthode .get() du dictionnaire.

Dans les rares cas où un nom n'existe pas (par exemple, votre fichier de configuration est en syntaxe Python et vous l'importez en tant que module Python plutôt que de l'analyser, et vous voulez que les utilisateurs puissent omettre certaines valeurs ... ou quelque chose d'aussi farfelue), vous pouvez utiliser getattr(), qui (comme celui .get()) dictionnaire accepte une valeur par défaut:

import config 
name = getattr(config, "name", "Guido") # rather than just name.config 

ou tout simplement laisser jeter un NameError et l'attraper.