2010-10-31 6 views
7

Groovy a un opérateur agréable pour déréférencement sûr, ce qui contribue à éviter NullPointerExceptions:déréférencement Safe en Python

variable?.method() 

Le method ne sera appelée, si variable n'est pas null.

Existe-t-il un moyen de faire la même chose en Python? Ou dois-je écrire if variable: variable.method()?

+1

@deamon: tout d'abord je ne sais pas Groovy et je ne veux pas discuter de ce que je ne sais pas, mais cette fonction (après avoir lu à ce sujet maintenant) ne me semble pas utile (et je peux me tromper et la plupart du temps je suis) car même si je fais quelque chose comme ça __variable.?method()__ oui si la variable est NULL ça ne déclenche pas d'erreur mais comment faire Je sais que la méthode a été appelée, parce qu'elle me ressemble comme une erreur de silence (en fait je n'ai jamais eu besoin de quelque chose comme ça) et si je fais quelque chose comme ça __a = variable.?method()__ donc je devrais faire __if (a) __ donc ..., ai-je raté quelque chose :) – mouad

+1

Je suis d'accord avec la singularité; Je ne vois pas comment cela pourrait être utile. Il ressemble à quelque chose que vous saupoudrez sur votre code pour cacher les erreurs. – adw

+0

@Seth Johnson: pouvez-vous être plus précis, ai-je dit quelque chose de mal et s'il s'agit de mon anglais est-ce si mauvais? ce n'est pas ma première langue :) – mouad

Répondre

10
  1. Non, il n'y en a pas. Mais pour vérifier None, vous n'écrivez pas if x:, vous écrivez if x is None:. Cette distinction est importante - x est évaluée à False des valeurs assez peu qui sont propably parfaitement valables (notamment les numéros 0 équivalent et collections vides), alors que x is Nonene évalue à True si la référence x des points à l'objet singleton None . D'après l'expérience personnelle, un tel opérateur serait très rarement nécessaire. Oui, None est parfois utilisé pour indiquer aucune valeur. Mais en quelque sorte - peut-être parce que le code idiomatique renvoie null objects où sensible ou jette des exceptions pour indiquer l'échec critique - je reçois seulement un AttributeError: 'NoneType' object has no attribute '...' deux fois par mois.

  2. Je dirais que cela pourrait être un mauvais fonctionnement. null a deux significations - "oublié d'initialiser" et "pas de données". Le premier est une erreur et devrait lever une exception. Le deuxième cas nécessite généralement une manipulation plus élaborée que "n'appelons pas cette méthode". Quand je demande à la base de données/ORM pour un UserProfile, il n'est pas là et je reçois null à la place ... est-ce que je veux passer silencieusement le reste de la méthode? Ou est-ce que je veux vraiment (quand dans "code de bibliothèque") jeter une exception approriate (ainsi "l'utilisateur (code)" sait que l'utilisateur n'est pas là et peut réagir ... ou l'ignorer) ou (quand je suis coder une fonction spécifique) afficher un message sensible ("Cet utilisateur n'existe pas, vous ne pouvez pas l'ajouter à votre liste d'amis") à l'utilisateur?

3

Python n'a rien de tel. C'est parce qu'il n'y a pas de pointeur null en Python. Eh bien, il y a la valeur spéciale None, qui est souvent utilisée dans des situations où elle représente "aucune valeur". Mais ce n'est qu'une convention. None est une valeur/objet comme tous les autres. Et puisqu'il n'y a aucun null, il n'y a aucun opérateur pour le traiter.

+1

Je suis d'accord, mais «Aucun» est essentiellement le même dans ce cas. Au lieu d'une exception 'NullPointerException' j'obtiendrais un' AttributeError', mais je ne pourrais pas appeler une méthode sur 'None' qui serait présent dans un objet habituel tel qu'une liste. – deamon

+1

Le fait est que «None» n'est pas du tout «inhabituel». C'est un objet avec une classe, des méthodes, etc.Il n'y a rien dans le langage qui le rende spécial (d'ailleurs, il est utilisé pour représenter la valeur "rien d'intéressant ici"). Alors, que testerait l'opérateur hypothétique «? Pour 'None' spécifiquement? Qu'en est-il des autres bibliothèques qui utilisent d'autres marqueurs (par exemple, NOT_FOUND dans PEAK)? – Dirk

+2

'None' est excellent pour marquer des arguments de fonction optionnels et d'autres choses, mais l'utiliser (ou quelque chose comme' NOT_FOUND') comme résultat "non trouvé" ou toute autre valeur de retour spéciale devrait être évitée. L'utilisation d'exceptions pour ces types de conditions exceptionnelles est préférable car elle tend à simplifier le code en utilisant ces fonctions (au lieu de vérifier chaque valeur de retour, vous pouvez avoir une clause except, ou simplement laisser l'exception monter en flèche). – adw

3

Un idiome que je l'ai vu et utilisé est callable(func) and func(a, b, c) en place d'un appel de fonction simple (où la valeur de retour n'est pas utilisé). Si vous essayez d'utiliser la valeur de retour, cependant, cet idiome donnera False si la fonction n'est pas appelable, ce qui peut ne pas être ce que vous voulez. Dans ce cas, vous pouvez utiliser l'opérateur ternaire pour fournir une valeur par défaut. Par exemple, si la fonction renvoie une liste que vous souhaitez parcourir, vous pouvez utiliser une liste vide comme valeur par défaut avec func(a, b, c) if callable(func) else [].

2

J'ai utilisé cette fonctionnalité dans Groovy, donc je ne vais pas répéter le paradoxe blub des autres affiches.

Dans une déclaration Groovy comme celui-ci

if(possiblyNull?.value){ 
    ... 

Est-ce en Python

try: 
    testVar = possiblyNull.value 
except: 
    testVar = None 
if(testVar): 

Il est sans aucun doute une fonctionnalité très Groovy, et est utile pour éliminer le bruit syntactique. Il y a quelques autres morceaux de sucre syntaxique, comme l'opérateur Elvis ou *, mais ils sacrifient la lisibilité comme dépense pour les symboles de correction rapide (en d'autres termes, ils ne sont pas des Pythonic).

Hope that helps :-)