2012-01-30 23 views
5

Duplicar posibles:
Python conditional assignment operatorPython equivalente de Perl/Ruby || =

Disculpas por una pregunta tan simple, pero googlear ||= no es muy útil;)

¿Existe un equivalente en Python a la declaración ||= que está presente en Ruby y Perl?

Por ejemplo:

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

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

también lo es el término general para algo como esto? La asignación condicional fue mi primera conjetura, pero el Wikipedia page no es exactamente lo que tenía en mente.

+0

Sí, parece ser un duplicado. Gracias Adam! –

+2

'$ foo || =" que "' reasignará '$ foo' si ya es * falso *. Por supuesto 'undef' es falso, pero también lo es cero y la cadena nula. Para reasignar solo un valor indefinido, use barras en su lugar, como '$ foo // =" what "' – Borodin

+0

Tenga en cuenta que '//' (y su extensión, '// =') se agregó en perl 5.10. Si todavía está atascado en 5.8.x, no podrá usar '// =' (y debería considerar seriamente actualizar si es posible). –

Respuesta

6

Un poco poco más detallado, pero la más fácil es

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

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

También puede utilizar el operador ternario

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

Sin embargo, si le he entendido, ||= asigna variables que antes no eran definido, sin queja? No tenía ni idea.

Para hacer que en el ámbito local, este patito feo podría funcionar

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

EDIT:

Acabo de ver el duplicado, y tiene un montón de soluciones, así :) Para los que son demasiado perezosos para mira, que también incluyen una variante más agradable en mi último

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

pero esto no va a funcionar para variables no definidas, solamente los valores Falsy serán sustituidos e indefinido elevará un NameError. Este próximo será, otoh, sólo funcionan para indefinida y mantener siempre el mismo valor Falsy preexistente, que como dice @Borodin es como //= en Perl

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

y, por supuesto, alguien utilizó una excepción :(

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

no, '|| =' reasignará una variable si es 'false'. Ver mi comentario sobre la pregunta. ¿Por qué esperarías una queja? – Borodin

+0

Gracias por la respuesta, al principio no noté la diferencia matizada. el 'bar = None' es requerido para que funcione, de lo contrario arroja un' NameError'. Para un comportamiento idéntico necesitas el fragmento 'locals() ['bar']'. Gracias de nuevo :) –

+0

@borodin No soy un Rubyista, solo lo he usado para cosas tontas como Chef. Solo quise decir que no sabía que 'undef' en Ruby era falsey, ya que ese no es el caso en Python (las referencias indefinidas arrojan excepciones).A pesar de todo, gracias por tus comentarios, aprendí algo :) –

1

No estoy seguro sobre el nombre lo mejor que podía llegar a decir:

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

usted casi nunca tienen indefinida en Python, y cuando lo hace por lo general significa que tiene m Ade un error.Sin embargo, convenientemente, la mayoría de los tipos de valores que comúnmente se utilizan como valores predeterminados (contenedores vacíos, cadenas de longitud cero, cero y None) son "falsos" en Python, por lo que a veces verá cosas como esta que aprovechan la forma operadores de Boole trabajo 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 razón por la que esto funciona es que Python se detiene evaluando or si el primer argumento es "Truthy", lo que se llama un cortocircuito, y en ambos casos devuelve el argumento real, en lugar de simplemente True o False, como resultado. Entonces, si name es "Jim", entonces "Jim" or "Guido" evalúa a "Jim" porque "Jim" es una cadena que no es de longitud cero y, por lo tanto, es "verdad".

Por supuesto, esto no funciona tan bien cuando no se conoce el tipo de valor que está tratando y/o un valor "falso" es un valor válido. Sin embargo, funciona bastante bien con cosas como archivos de configuración y raw_input() donde un valor faltante devolverá una cadena vacía:

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

Otro idioma común se utiliza cuando se trata de artículos en un diccionario. El método de la clase del diccionario get() le permite especificar un valor predeterminado para usar si la variable no está en el diccionario.

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

Esto puede ser usado cuando su función se ha pasado los argumentos de palabras clave utilizando la convención **kwargs. Usted podría también lo utilizan con variables, como los globals() y locals() funciones devuelven, respectivamente, todas las variables globales o locales actualmente en su alcance como un diccionario:

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

Sin embargo, como ya he dicho, se le rara vez tienen variables realmente indefinidas en Python. En casos como marcos web, se le pasarán argumentos de cadena de consulta como un diccionario, por ejemplo, y puede usar el método .get() del diccionario en él.

En el raro caso en que un nombre realmente no existe (por ejemplo, su archivo de configuración está en sintaxis de Python y lo está importando como un módulo de Python en lugar de analizarlo, y desea que los usuarios puedan omitir algunos valores ... o algo igual de loco), puede utilizar getattr(), que (como .get() del diccionario) acepta un valor por defecto:

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

o simplemente dejar que lanzar una NameError y atraparlo.