2011-03-10 4 views
0

Si la fonction retourne une liste de deux valeurs ou un tuple en cas de succès ou Faux en cas d'échec, comment puis-je décompresser la liste de retour en deux variables tout en vérifiant Faux?Affectation de déballage Python idiomatique ou Faux

def get_key_value(): 
    if (cond != True): 
    return False 
    return [val1, val2] 

# Call it 
# How can I also check for False while unpacking? 
key, value = get_key_value() 
+7

Peut-être qu'il serait préférable de jeter une exception au lieu de retourner deux types de valeurs différentes. –

Répondre

4

Coverting @Felix Kling's excellent commentaire dans une réponse. Si vous ne parvenez pas à trouver une paire (clé, valeur) indique une sorte de défaillance du système, il est préférable de lancer une exception. Si votre échec ne correspond pas à l'un des standard exceptions, vous devez créer votre propre type d'exception. Le cond != True mieux vaut not cond. Aussi, il vaut mieux ne pas créer une liste si ce n'est pas nécessaire.

class DataNotFound(Exception): pass 

def get_key_value(): 
    if not cond: 
    raise DataNotFound("Couldn't find it!") 
    return val1, val2 

try: 
    key,value = get_key_value() 
except DataNotFound: 
    #handle the failure somehow 
    key, value = 'ERROR', 'ERROR' 
+1

+1 Juste deux détails: 'si pas cond:' et 'return (val1, val2)'. – delnan

+1

Je suis d'accord avec @delnan, 'if not cond' est BEAUCOUP préféré à' if cond! = True'. Quant au retour, même juste 'return val1, val2' suffira. – PaulMcG

3

Cela relève de la politique "Easier to Ask for Forgiveness than Permission" de Python. J'évite d'attraper TypeError dans votre fonction, au cas où il y aurait un autre problème imprévu.

data = get_key_value() 
try: 
    key, value = data 
except TypeError: 
    #handle the failure somehow 
    key, value = 'ERROR', 'ERROR' 
1

Je ne pense pas qu'il y est une façon idiomatiques de le faire - pas moins car une fonction qui se comporte de cette façon elle-même est unidiomatic. Si vous devez le faire, je vous suggère de simplement utiliser le fait que votre liste de 2 éléments ou tuple est une valeur "vérité" plutôt que "fausse" (ce n'est pas une terminologie Python mais c'est utile):

pair_or_false = get_key_value() 
if pair: 
    key,value = val 
else: 
    # handle failure in whatever way 

l'alternative évidente est de traiter le cas non trouvé comme une exception:

try: 
    key,value = get_key_value() 
except TypeError: 
    # deal with not-found case 

mais s'il y a une possibilité à tout ce autre chose que le décompactage échoué pourrait soulever un TypeError alors vous courez le risque de masquer une véritable erreur de cette façon.

+0

Je l'avais traité avec votre première méthode 'if/else' mais j'espérais réduire mon nombre de lignes puisque la fonction est appelée plusieurs fois. Je vais voir comment cela fonctionne en attrapant 'TypeError'. L'application est une analyse DOM assez simple et le risque est faible pour les autres 'TypeErrors'. Merci. –

1

Vous rencontrez des problèmes car vous mélangez des types de retour. Juste parce que vous pouvez ne signifie pas que vous devriez. Bien que je suis d'accord avec les autres ici qu'une exception est une bonne façon de procéder, cela peut dépendre de si vous vous attendez à trouver une valeur de clé valide & la plupart du temps. Si tel est le cas, utilisez une exception (quelque chose comme KeyError) pour indiquer que la fonction a échoué. Mais si vous vous attendez à ce qu'il échoue à un taux élevé, vous ne pouvez pas vouloir les frais généraux d'exception. Dans ce cas, le retour quelque chose comme [None, None] de get_key_value puis votre code d'appel ressemblerait à ceci:

key, value = get_key_value() 
if key: 
    # take action 
else: 
    # handle the error appropriately