Una línea si-condición-asignación


140

Tengo el siguiente código

num1 = 10
someBoolValue = True

Necesito establecer el valor de num1to 20if someBoolValueis True; y no hacer nada de otra manera. Entonces, aquí está mi código para eso

num1 = 20 if someBoolValue else num1

¿Hay alguna forma de evitar la ...else num1parte para que se vea más limpia? Un equivalente a

if someBoolValue:
    num1 = 20

Probé su sustitución por ...else passla siguiente: num1=20 if someBoolValue else pass. Todo lo que obtuve fue un error de sintaxis. Tampoco podría omitir la ...else num1parte.


2
Solo cámbialo todo a num1 = 20 if someBoolValue else 10. ¿Entonces guardas la num1=10línea también?
Thomas Ahle

Gracias. Pero este no es exactamente mi código. Quiero decir que num1ya existe ...
bdhar

Respuestas:


196

No creo que esto sea posible en Python, ya que lo que realmente estás tratando de hacer probablemente se expanda a algo como esto:

num1 = 20 if someBoolValue else num1

Si excluye else num1, recibirá un error de sintaxis ya que estoy bastante seguro de que la asignación debe devolver algo.

Como otros ya han mencionado, podría hacer esto, pero es malo porque probablemente terminará confundiéndose cuando lea ese código la próxima vez:

if someBoolValue: num1=20

No soy un gran admirador del num1 = someBoolValue and 20 or num1por exactamente el mismo motivo. Realmente tengo que pensar dos veces en lo que está haciendo esa línea.

La mejor manera de lograr lo que quieres hacer es la versión original:

if someBoolValue:
    num1 = 20

La razón por la que es la mejor versión es porque es muy obvio lo que quieres hacer, y no te confundirás a ti mismo ni a nadie más que se pondrá en contacto con ese código más adelante.

Además, como nota al margen, num1 = 20 if someBoolValuees un código válido de Ruby, porque Ruby funciona un poco diferente.


8
Según PEP-308 ( docs.python.org/2.5/whatsnew/pep-308.html ), la expresión condicional se puede aclarar si se coloca en paren, como en num1 = (20 if someBoolValue else num1).
haridsv

46

Utilizar este:

num1 = 20 if someBoolValue else num1

3
esto es lo que he estado usando ... y buscando una alternativa ... ¡gracias de todos modos!
bdhar

¿Cómo llamar a este bloque? Quiero decir, ¿cómo se llama?
Fuat

1
es un operador ternario
Chris Maes

Uno no debería usar este enfoque si recorre grandes conjuntos de datos, ya que introduce una asignación innecesaria en caso de que terminemos en la instrucción else.
dapc

21

En una linea:

if someBoolValue: num1 = 20

Pero no hagas eso. Este estilo normalmente no se espera. Las personas prefieren la forma más larga para mayor claridad y consistencia.

if someBoolValue:
    num1 = 20

(Igualmente, se deben evitar las gorras de camello. Por lo tanto, úselo some_bool_value).

Tenga en cuenta que no existe una expresión en línea some_value if predicatesin una elseparte porque no habría un valor de retorno si el predicado fuera falso. Sin embargo, las expresiones deben tener un valor de retorno claramente definido en todos los casos. Esto es diferente del uso como en, por ejemplo, Ruby o Perl.


2
Porque se hace difícil de leer y probablemente terminarás confundido por tu propio código, y eso nunca es una buena idea.
Frost

@bdhar, ¿por qué quieres ponerlo en una línea? No correrá más rápido, será más difícil de leer para otras personas
John La Rooy

1
@gnibbler, no hay razón, en realidad. Estaba buscando una forma más corta con mejor legibilidad ..
bdhar

17

puede usar uno de los siguientes:

(falseVal, trueVal)[TEST]

TEST and trueVal or falseVal

1
Asignación condicional de one one liner
minhas23

¿Cómo se llama esa "estructura"? Nunca he visto eso en ~ 6 meses de aprendizaje de Python.
Guimoute

1
Al menos estas no son tareas, a menos que pongas una delante de ellas, y en segundo lugar, no funcionarán de la manera descrita aquí. El primero crea una tupla, luego elige uno de sus elementos por índice. Solo funcionará para las pruebas que devuelven un número entero entre -1 y 1, o True/ False, ya que booles una subclase de int. En todos los casos donde la prueba devuelve algo que simplemente evaluaría verdadero, falla con una excepción. El segundo solo funciona siempre y cuando trueValno se evalúe falso en sí mismo, lo que daría lugar a falseValser asignado incluso si la prueba fuera verdadera.
Bachsau

es bastante corto, pero también muy difícil de usar con seguridad como "patrón recomendado", vea el comentario anterior de Bachsau ... (así que lo
rechacé

6

No. Supongo que esperabas que algo así num1 = 20 if someBoolValuefuncionara, pero no es así. Creo que la mejor manera es con la ifdeclaración tal como la has escrito:

if someBoolValue:
    num1 = 20

5
num1 = 10 + 10*(someBoolValue is True)

Esa es mi nueva respuesta final. La respuesta previa fue la siguiente y fue excesivo para el problema declarado. Getting_too_clever == not Good. Aquí está la respuesta anterior ... sigue siendo bueno si desea agregar una cosa para Truecond y otra para False:

num1 = 10 + (0,10)[someBoolValue is True]

Usted mencionó num1que ya tendría un valor que debería dejarse solo. Supuse num1 = 10que esa es la primera declaración de la publicación, por lo que la operación para llegar 20es agregar 10.

num1 = 10
someBoolValue = True

num1 = 10 + (0,10)[someBoolValue is True]

print(f'num1 = {num1}\nsomeBoolValue = {someBoolValue}')

producido esta salida

num1 = 20
someBoolValue = True

Ahora estoy pensando que debería haber respondido 'num1 = 10 + 10 * (someBoolValue == True)' Problema definido como la condición 'False' como un no-op básicamente. Si era necesario elegir agregar un valor diferente para 'Falso', entonces la respuesta previa es mejor. ¿Edito mi publicación o hago esto en los comentarios?
MikeyB


2

Si desea invocar un método si algo booleano es verdadero, puede poner else Nonefin al trinario.

>>> a=1
>>> print(a) if a==1 else None
1
>>> print(a) if a==2 else None
>>> a=2
>>> print(a) if a==2 else None
2
>>> print(a) if a==1 else None
>>>

1

Si definitivamente va a suceder un código de línea, Python 3.8 presenta expresiones de asignación cariñosamente conocidas como "el operador de la morsa".

:=

someBoolValue and (num := 20)

Se 20asignará a numsi la primera expresión booleana es True. La asignación debe estar entre paréntesis aquí, de lo contrario obtendrá un error de sintaxis.

num = 10
someBoolValue = True

someBoolValue and (num := 20)
print(num) # 20

num = 10
someBoolValue = False

someBoolValue and (num := 20)
print(num) # 10

0

Para el futuro viajero del tiempo de google, aquí hay una nueva forma (disponible desde Python 3.8 en adelante):

b = 1
if a := b:
    # this section is only reached if b is not 0 or false.
    # Also, a is set to b
    print(a, b)

-1

Definitivamente puede usar num1 = (20 si someBoolValue else num1) si lo desea.


¿Duplicado de la (s) respuesta (s) anterior?
Adam Smith

-1

Esto es lo que puedo sugerir. Use otra variable para derivar la cláusula if y asígnela a num1.

Código:

num2 =20 if someBoolValue else num1
num1=num2


-1

Puedes hacerlo de esta manera.

try:
    a = [i for i in [20] if False][0]
except IndexError:
    print("Do what ever you want here")

Puede resolver su problema de esta manera, pero usar 'probar / excepto bloquear' no es la mejor práctica para python.

Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.