Páginas

Saturday, August 8, 2009

If-else em uma linha de Python

Hoje aprendi mais uma forma [tosca] de fazer condicional com Python.

Depois do truque lógico do "condicao and valor_caso_verdadeiro or valor_caso_falso", o que descobri navegando na Internet hoje foi:

>>> x = 5
>>> ["menor que 10", "maior que 10"][x > 10]
'menor que 10'

Isso funciona porque o tipo bool (valor booleano) é um subclasse do tipo int, tipo requerido em indices de sequências.

>>> ["menor que 10", "maior que 10"]['not an integer']
TypeError: list indices must be integers

>>> issubclass(bool, int)
True

>>> ["menor que 10", "maior que 10"][True]
'maior que 10'


Mas é claro que isso é só um "acidente" e não deve ser usado normalmente. A partir do Python 2.5 temos a sintaxe:

valor_caso_verdadeiro if condicao else valor_caso_falso

3 comments:

Israel Teixeira said...

De qq forma, interessante.

Anonymous said...

Oi Rodolfo,

Só algumas observações de 'segurança' para cada uma dessas técnicas :)

1 - em condicao and verdadeiro or falso – é sempre bom lembrar que para Python os valores "", (), [], {}, 0, None e tudo o que retorna 0 em __len__() ou em __nonzero__() são considerados FALSO. Portanto se o valor 'verdadeiro' na verdade for um desses valores ele não será retornado.

2 - para esse caso é sempre bom tomar cuidado para não fazer algo como [ func_a("x"), func_b("x") ][ v == "b" ]. Não podemos nos esquecer que ambas as funções (func_a e func_b) serão executadas antes da condição "v == 'b'" ser avaliada.

No caso da nova expressão if/else que apareceu no Python 2.5 tá 'tudo certo'. Só colocar um ( ) em torno dela pra 'garantir' a precedência :)

Cuidando disso e garantindo a boa legibilidade do código (que é o mais importante) podem 'mandar bala' com qualquer uma dessas alternativas. :)

Rodolfo said...

Bem lembrado Osvaldo.
Apesar de eu não ter entrado no mérito de explicar o truque do "and or", é sempre bom explicar pros afoitos que isso não é equivalente ao if else como você já explicitou.

Eu só indico usar curto-circuito lógico só em casos especiais, e quando souber muito bem o que está fazendo... mas uma vez, legibilidade conta e muito.

E por isso mesmo o truque principal [a,b][cond] é só uma brincadeira... não vejo nunca isso sendo usado em código de verdade.

De qualquer forma, tem como fazer o que você propôs:

[func_a, func_b][v == 'b']("x")

É só chamar a função na hora que você quer que ela seja chamada...

[]'s