2010-08-05 3 views
2

Je voudrais faire quelque chose comme:Qu'est-ce que Python équivaut à ou équivaut à expression, pour obtenir le retour de foo ou foo = 'bar' fonctionnant?

def get_foo(): 
    return self._foo or self._foo = Bar() 

Je cherche la manière la plus propre de le faire. Est-ce possible avec ou égal?

Mes tentatives ont échoué:

>>> foo = None 
>>> foo or 'bar' 
'bar' 
>>> foo 
>>> foo or foo = 'bar' 
    File "<stdin>", line 1 
SyntaxError: can't assign to operator 
>>> foo or (foo = 'bar') 
    File "<stdin>", line 1 
    foo or (foo = 'bar') 
       ^
SyntaxError: invalid syntax 

Répondre

6

En Python, vous ne pouvez pas utiliser d'affectations dans les expressions. Donc, vous devez faire la mission et la déclaration return sur deux lignes différentes:

def get_foo(self): 
    self._foo = self._foo or Bar() 
    return self._foo 

Mais en général, il est préférable de l'écrire:

def get_foo(self): 
    if not self._foo: 
     self._foo = Bar() 
    return self._foo 
+0

Qu'est-ce qui est le plus rapide? Dans le premier cas, python est-il assez intelligent pour ne pas effectuer l'opération d'affectation si la valeur est définie? –

+0

Oui. Il n'y a pratiquement rien dedans. – katrielalex

+3

@WooYek: Si vous vous inquiétez autant de la performance, alors soit cette méthode devrait être éliminée complètement et aller pour les membres statiques initialisés, soit Python peut ne pas être le langage que vous recherchez. En général, l'écrire comme vous le voulez (le court chemin) est mauvais parce que c'est illisible et conduit à un code non maintenu. – Ivo

4

opérateur d'affectation de Python ne passe pas par la valeur attribuée, principalement parce que dans d'autres langues, il est avéré être un générateur fécond de bugs accidentels =/==. Au lieu de cela, vous devez être explicite:

def get_foo(self): 
    if self._foo is None: 
     self._foo= Bar() 
    return self._foo 

Vous pouvez faire une expression avec des effets secondaires si vous voulez vraiment:

def set_foo(self, v): 
    self._foo= v 
    return v 

return self._foo or self.set_foo(Bar()) 

mais il est généralement considéré comme une mauvaise chose.

-1

Je peux me tromper, mais cela ressemble un travail pour l'opérateur ||=.

def get_foo(): 
    return self._foo |= Bar() 

Mon Perl est rouillé au mieux, mais || = semble renvoyer une valeur R, de sorte que le rendement devrait fonctionner.

Modifier: Woopsie, ceci est Python. Il n'a pas de ||=. Bummer.

Ensuite, j'utiliser le simulated ternary operator:

def get_foo() 
    self._foo = self._foo is None and Bar() or self._foo 
    return self._foo 

Edit 2: Python a un vrai opérateur ternaire. Utilisez-le au lieu de ce qui précède.

def get_foo() 
    self._foo = Bar() if self._foo is None else self._foo 
    return self._foo 
+0

Je pense qu'il n'y a pas de || = 'en python. –

+1

Il ya * un * opérateur ternaire en Python (2.6+ je crois): 'self._foo = self._foo si self._foo else Bar()'. – Ivo

+2

"cond et is-true-value ou cond-is-false-value" a toujours été sujette à erreur (si la valeur cond-is-true est l'une des valeurs de Python comme 0, [], {}, etc. que Python considère comme faux dans son booléen). Initialisez self._foo à None, et utilisez ce ternaire approprié (commençant par Py2.5): 'self._foo = Bar() si self._foo est None else self._foo'. Mais pourquoi assigner self._foo à self._foo dans le cas 99% où self._foo n'est plus None une fois qu'il a été initialisé? Utilisez juste 'si self._foo est None: self._foo = Bar()' suivi de 'return self._foo'. Pas de magie ternaire, juste du code facile à lire. – PaulMcG

Questions connexes