Se o Python não possui um operador condicional ternário, é possível simular um usando outras construções de linguagem?
case [...] { when ... then ...} [ else ... ] end
um efeito semelhante, mas nem um pouco ternário.
Se o Python não possui um operador condicional ternário, é possível simular um usando outras construções de linguagem?
case [...] { when ... then ...} [ else ... ] end
um efeito semelhante, mas nem um pouco ternário.
Respostas:
Sim, foi adicionado na versão 2.5. A sintaxe da expressão é:
a if condition else b
Primeiro condition
é avaliado e, em seguida, exatamente um de um a
ou b
é avaliado e retornado com base no valor booleano de condition
. Se condition
avalia para True
, então a
é avaliado e retornado, mas b
é ignorado; caso contrário, quando b
é avaliado e retornado, mas a
é ignorado.
Isso permite um curto-circuito, porque quando condition
somente verdadeiro a
é avaliado e b
não é avaliado, mas quando condition
é falso somente b
é avaliado e a
não é avaliado.
Por exemplo:
>>> 'true' if True else 'false'
'true'
>>> 'true' if False else 'false'
'false'
Observe que condicionais são uma expressão , não uma declaração . Isso significa que você não pode usar instruções de atribuição pass
ou outras instruções dentro de uma expressão condicional :
>>> pass if False else x = 3
File "<stdin>", line 1
pass if False else x = 3
^
SyntaxError: invalid syntax
No entanto, você pode usar expressões condicionais para atribuir uma variável da seguinte maneira:
x = a if True else b
Pense na expressão condicional como alternando entre dois valores. É muito útil quando você está em uma situação de "um valor ou outro", mas não faz muito mais.
Se você precisar usar instruções, precisará usar uma if
instrução normal em vez de uma expressão condicional .
Lembre-se de que alguns Pythonistas são desaprovados por vários motivos:
condition ? a : b
operador ternário clássico de muitas outras linguagens (como C, C ++, Go, Perl, Ruby, Java, Javascript, etc.), que podem levar a erros quando pessoas não familiarizadas com o Python " comportamento surpreendente "use-o (eles podem reverter a ordem dos argumentos).if
' possa ser realmente útil e torne seu script mais conciso, ele realmente complica seu código)Se estiver com problemas para lembrar a ordem, lembre-se de que, quando lido em voz alta, você (quase) diz o que quer dizer. Por exemplo, x = 4 if b > 8 else 9
é lido em voz alta como x will be 4 if b is greater than 8 otherwise 9
.
Documentação oficial:
f(x) = |x| = x if x > 0 else -x
parece muito natural para os matemáticos. Você também pode entendê-lo como fazer A na maioria dos casos, exceto quando C, em seguida, você deve fazer B ...
z = 3 + x if x < y else y
. Se x=2
e y=1
, você pode esperar que produza 4, mas na verdade produziria 1. z = 3 + (x if x > y else y)
é o uso correto.
z = 3 + x if x < y else 3 + y
) ou agrupar a condicional ( z = 3 + (x if x < y else y)
ou z = (x if x < y else y) + 3
)
Você pode indexar em uma tupla:
(falseValue, trueValue)[test]
test
precisa retornar Verdadeiro ou Falso .
Pode ser mais seguro implementá-lo sempre como:
(falseValue, trueValue)[test == True]
ou você pode usar o built-in bool()
para garantir um valor booleano :
(falseValue, trueValue)[bool(<expression>)]
(lambda: print("a"), lambda: print("b"))[test==true]()
[]
s pode ser uma expressão arbitrária. Além disso, por segurança, você pode testar explicitamente a veracidade escrevendo [bool(<expression>)]
. A bool()
função existe desde a v2.2.1.
True
e False
como as chaves: {True:trueValue, False:falseValue}[test]
não sei se isso é menos eficiente, mas evita pelo menos todo debate "elegante" vs. "feio". Não há ambiguidade em lidar com um booleano, e não com um int.
Para versões anteriores à 2.5, há o truque:
[expression] and [on_true] or [on_false]
Pode dar resultados errados quando on_true
tem um valor booleano falso. 1
Embora tenha o benefício de avaliar expressões da esquerda para a direita, o que é mais claro na minha opinião.
<expression 1> if <condition> else <expression 2>
a = 1
b = 2
1 if a > b else -1
# Output is -1
1 if a > b else -1 if a < b else 0
# Output is -1
A partir da documentação :
Expressões condicionais (às vezes chamadas de "operador ternário") têm a menor prioridade de todas as operações do Python.
A expressão
x if C else y
primeiro avalia a condição C ( não x ); se C for verdadeiro, x é avaliado e seu valor é retornado; caso contrário, y é avaliado e seu valor é retornado.Veja PEP 308 para mais detalhes sobre expressões condicionais.
Novo desde a versão 2.5.
Um operador para uma expressão condicional no Python foi adicionado em 2006 como parte da Proposta de aprimoramento do Python 308 . Sua forma difere do ?:
operador comum e é:
<expression1> if <condition> else <expression2>
que é equivalente a:
if <condition>: <expression1> else: <expression2>
Aqui está um exemplo:
result = x if a > b else y
Outra sintaxe que pode ser usada (compatível com versões anteriores à 2.5):
result = (lambda:y, lambda:x)[a > b]()
onde operandos são avaliados preguiçosamente .
Outra maneira é indexar uma tupla (que não é consistente com o operador condicional da maioria dos outros idiomas):
result = (y, x)[a > b]
ou dicionário explicitamente construído:
result = {True: x, False: y}[a > b]
Outro método (menos confiável), mas mais simples, é usar and
e or
operadores:
result = (a > b) and x or y
no entanto, isso não vai funcionar se x
seriaFalse
.
Uma solução possível é criar x
e y
listar ou tuplas conforme a seguir:
result = ((a > b) and [x] or [y])[0]
ou:
result = ((a > b) and (x,) or (y,))[0]
Se você estiver trabalhando com dicionários, em vez de usar uma condicional ternária, poderá aproveitar get(key, default)
, por exemplo:
shell = os.environ.get('SHELL', "/bin/sh")
Fonte: ?: Em Python na Wikipedia
result = {1: x, 0: y}[a > b]
é uma outra variante possível ( True
e False
são números inteiros com valores efectivamente 1
e 0
)
Infelizmente, o
(falseValue, trueValue)[test]
solução não tem comportamento de curto-circuito; portanto, ambos falseValue
e trueValue
são avaliados independentemente da condição. Isto pode ser sub-tima ou mesmo buggy de (ou seja, tanto trueValue
efalseValue
podem ser métodos e ter efeitos colaterais).
Uma solução para isso seria
(lambda: falseValue, lambda: trueValue)[test]()
(execução atrasada até que o vencedor seja conhecido;)), mas introduz inconsistência entre objetos que podem ser chamados e não chamados. Além disso, ele não resolve o caso ao usar propriedades.
E assim continua a história - escolher entre as três soluções mencionadas é uma troca entre ter o recurso de curto-circuito, usar pelo menos o Зython 2.5 (IMHO não é mais um problema) e não estar propenso a erros " trueValue
-valoriza-para-falso" .
if else if
.
Aqui, apenas tento mostrar alguma diferença importante ternary operator
entre algumas linguagens de programação.
Operador ternário em Javascript
var a = true ? 1 : 0;
# 1
var b = false ? 1 : 0;
# 0
Operador ternário em Ruby
a = true ? 1 : 0
# 1
b = false ? 1 : 0
# 0
Operador ternário em Scala
val a = true ? 1 | 0
# 1
val b = false ? 1 | 0
# 0
Operador ternário em programação R
a <- if (TRUE) 1 else 0
# 1
b <- if (FALSE) 1 else 0
# 0
Operador ternário em Python
a = 1 if True else 0
# 1
b = 1 if False else 0
# 0
Para o Python 2.5 e mais recente, há uma sintaxe específica:
[on_true] if [cond] else [on_false]
Nos Pythons mais antigos, um operador ternário não é implementado, mas é possível simulá-lo.
cond and on_true or on_false
No entanto, existe um problema em potencial que, se cond
avaliado True
e on_true
avaliado False
, on_false
é retornado em vez de on_true
. Se você deseja esse comportamento, o método está OK, caso contrário, use o seguinte:
{True: on_true, False: on_false}[cond is True] # is True, not == True
que pode ser envolvido por:
def q(cond, on_true, on_false)
return {True: on_true, False: on_false}[cond is True]
e usado desta maneira:
q(cond, on_true, on_false)
É compatível com todas as versões do Python.
q("blob", on_true, on_false)
retorna on_false
, enquanto on_true if cond else on_false
retorna on_true
. A solução é substituir cond
com cond is not None
nestes casos, apesar de que não é uma solução perfeita.
bool(cond)
vez de cond is True
? O primeiro verifica a veracidade de cond
, o último verifica a igualdade de ponteiros com o True
objeto. Como destacado por @AndrewCecil, "blob"
é verdade, mas é is not True
.
[on_false, on_True][cond is True]
para que a expressão fique mais curta.
Você pode encontrar frequentemente
cond and on_true or on_false
mas isso leva a um problema quando on_true == 0
>>> x = 0
>>> print x == 0 and 0 or 1
1
>>> x = 1
>>> print x == 0 and 0 or 1
1
onde você esperaria de um operador ternário normal esse resultado
>>> x = 0
>>> print 0 if x == 0 else 1
0
>>> x = 1
>>> print 0 if x == 0 else 1
1
O Python tem um operador condicional ternário?
Sim. No arquivo de gramática :
test: or_test ['if' or_test 'else' test] | lambdef
A parte de interesse é:
or_test ['if' or_test 'else' test]
Portanto, uma operação condicional ternária é da forma:
expression1 if expression2 else expression3
expression3
será avaliado preguiçosamente (ou seja, avaliado apenas se expression2
for falso em um contexto booleano). E por causa da definição recursiva, você pode encadear indefinidamente (embora possa ser considerado um estilo ruim).
expression1 if expression2 else expression3 if expression4 else expression5 # and so on
Observe que todos if
devem ser seguidos com um else
. As pessoas que aprendem a compreensão da lista e as expressões geradoras podem achar que essa é uma lição difícil de aprender - o seguinte não funcionará, pois o Python espera uma terceira expressão para outra pessoa:
[expression1 if expression2 for element in iterable]
# ^-- need an else here
o que gera a SyntaxError: invalid syntax
. Portanto, o exposto acima é uma parte incompleta da lógica (talvez o usuário espere um não operacional na condição falsa) ou o que pode ser pretendido é usar o expression2 como um filtro - observa que o seguinte é Python legal:
[expression1 for element in iterable if expression2]
expression2
funciona como um filtro para a compreensão da lista e não é um operador condicional ternário.
Você pode achar um pouco doloroso escrever o seguinte:
expression1 if expression1 else expression2
expression1
terá que ser avaliado duas vezes com o uso acima. Pode limitar a redundância se for simplesmente uma variável local. No entanto, um idioma pitonico comum e com bom desempenho para este caso de uso é usar or
o comportamento de atalho:
expression1 or expression2
o que é equivalente em semântica. Observe que alguns guias de estilo podem limitar esse uso com base na clareza - ele inclui muito significado em muito pouca sintaxe.
expression1 or expression2
sendo semelhante e com os mesmos inconvenientes / positivos que expression1 || expression2
em javascript
expressionN
para todas as instâncias seja consistente, pode ser mais fácil entender com nomes que distinguem a expressão de teste condicional das duas expressões de resultado; por exemplo result1 if condition else result2
,. Isso é especialmente evidente ao aninhar (também conhecido como encadeamento):result1 if condition1 else result2 if condition2 else result3
. Vê quanto melhor isso é lido dessa maneira?
Simulando o operador ternário python.
Por exemplo
a, b, x, y = 1, 2, 'a greather than b', 'b greater than a'
result = (lambda:y, lambda:x)[a > b]()
resultado:
'b greater than a'
result = (y, x)[a < b]
Por que você usa a lambda
função ?
O operador condicional ternário simplesmente permite testar uma condição em uma única linha, substituindo a multilinha, caso contrário, tornando o código compacto.
[on_true] if [expression] else [on_false]
# Program to demonstrate conditional operator
a, b = 10, 20
# Copy value of a in min if a < b else copy b
min = a if a < b else b
print(min) # Output: 10
# Python program to demonstrate ternary operator
a, b = 10, 20
# Use tuple for selecting an item
print( (b, a) [a < b] )
# Use Dictionary for selecting an item
print({True: a, False: b} [a < b])
# lamda is more efficient than above two methods
# because in lambda we are assure that
# only one expression will be evaluated unlike in
# tuple and Dictionary
print((lambda: b, lambda: a)[a < b]()) # in output you should see three 10
# Python program to demonstrate nested ternary operator
a, b = 10, 20
print ("Both a and b are equal" if a == b else "a is greater than b"
if a > b else "b is greater than a")
A abordagem acima pode ser escrita como:
# Python program to demonstrate nested ternary operator
a, b = 10, 20
if a != b:
if a > b:
print("a is greater than b")
else:
print("b is greater than a")
else:
print("Both a and b are equal")
# Output: b is greater than a
if-else
não é realmente uma reescrita do operador ternário e produzirá uma saída diferente para os valores selecionados de aeb (especificamente se um for um tipo que implementa um __ne__
método estranho ).
você consegue fazer isso :-
[condition] and [expression_1] or [expression_2] ;
Exemplo:-
print(number%2 and "odd" or "even")
Isso imprimiria "ímpar" se o número for ímpar ou "par" se o número for par.
Nota :- 0, Nenhum, Falso, lista vazia, emptyString é avaliado como Falso. E qualquer dado diferente de 0 é avaliado como True.
se a condição [condição] se tornar "Verdadeira", a expressão_1 será avaliada, mas não a expressão_2. Se "e" algo com 0 (zero), o resultado será sempre rápido. Portanto, na instrução abaixo,
0 and exp
A expressão exp não será avaliada, pois "e" com 0 sempre será avaliado como zero e não há necessidade de avaliar a expressão. É assim que o próprio compilador funciona, em todos os idiomas.
No
1 or exp
a expressão exp não será avaliada, pois "ou" com 1 sempre será 1. Portanto, não será necessário avaliar a expressão exp, pois o resultado será 1 de qualquer maneira. (métodos de otimização do compilador).
Mas no caso de
True and exp1 or exp2
A segunda expressão exp2 não será avaliada desde True and exp1
seria True quando exp1 não for falsa.
Da mesma forma em
False and exp1 or exp2
A expressão exp1 não será avaliada, pois False equivale a escrever 0 e fazer "e" com 0 seria 0 em si, mas após exp1, uma vez que "ou" é usado, ele avaliará a expressão exp2 após "ou".
Nota:- Esse tipo de ramificação usando "ou" e "e" só pode ser usado quando a expressão_1 não tiver um valor de Verdadeiro Falso (ou 0 ou Nenhum ou lista vazia [] ou cadeia de caracteres vazia ''.), Pois se expressão_1 se tornar False, a expressão_2 será avaliada devido à presença "ou" entre exp_1 e exp_2.
Caso você ainda deseje fazê-lo funcionar em todos os casos, independentemente dos valores verdadeiros exp_1 e exp_2, faça o seguinte: -
[condition] and ([expression_1] or 1) or [expression_2] ;
x = [condition] and ([expression_1] or 1) or [expression_2]
e expression_1
avalia como falso, x
será 1
, não expression_1
. Use a resposta aceita.
Mais uma dica do que uma resposta (não é necessário repetir o óbvio pelo tempo hundreth), mas às vezes eu o uso como um atalho oneliner em tais construções:
if conditionX:
print('yes')
else:
print('nah')
, torna-se:
print('yes') if conditionX else print('nah')
Alguns (muitos :) podem parecer desonestos (até mesmo, rubi-ish :), mas pessoalmente acho mais natural - ou seja, como você o expressaria normalmente, além de um pouco mais atraente visualmente em grandes blocos de código.
print( 'yes' if conditionX else 'nah' )
a sua resposta. :-)
print()
nos dois casos - e parece um pouco mais pitônico, devo admitir :) Mas e se as expressões / funções não forem as mesmas - como print('yes') if conditionX else True
- para obter o print()
único na verdadeconditionX
print('yes') if conditionX else print('nah')
é que ele fornece um SyntaxError no Python2.
print "yes"
enquanto no Python 3 é uma função - print("yes")
. Isso pode ser resolvido usando-o como uma declaração ou melhor - from future import print_function
.
Uma das alternativas à expressão condicional do Python
"yes" if boolean else "no"
é o seguinte:
{True:"yes", False:"no"}[boolean]
que tem a seguinte boa extensão:
{True:"yes", False:"no", None:"maybe"}[boolean_or_none]
A alternativa mais curta permanece:
("no", "yes")[boolean]
mas não há alternativa para
yes() if boolean else no()
se você deseja evitar a avaliação de yes()
e no()
, porque em
(no(), yes())[boolean] # bad
ambos no()
e yes()
são avaliados.
Muitas linguagens de programação derivadas C
geralmente têm a seguinte sintaxe de operador condicional ternário:
<condition> ? <expression1> : <expression2>
A princípio, o
Python
B enevolente D ictator F ou L ife (quero dizer, Guido van Rossum, é claro) rejeitaram (como estilo não-Pythonic), já que é muito difícil de entender para as pessoas não costumavamC
idioma. Além disso, o sinal de dois pontos:
já tem muitos usosPython
. Após a aprovação do PEP 308 ,Python
finalmente recebeu sua própria expressão condicional de atalho (o que usamos agora):
<expression1> if <condition> else <expression2>
Então, primeiro ele avalia a condição. Se retornar True
, a expressão1 será avaliada para fornecer o resultado, caso contrário, a expressão2 será avaliada. Devido à mecânica da Lazy Evaluation - apenas uma expressão será executada.
Aqui estão alguns exemplos (as condições serão avaliadas da esquerda para a direita):
pressure = 10
print('High' if pressure < 20 else 'Critical')
# Result is 'High'
Os operadores ternários podem ser encadeados em série:
pressure = 5
print('Normal' if pressure < 10 else 'High' if pressure < 20 else 'Critical')
# Result is 'Normal'
O seguinte é o mesmo que o anterior:
pressure = 5
if pressure < 20:
if pressure < 10:
print('Normal')
else:
print('High')
else:
print('Critical')
# Result is 'Normal'
Espero que isto ajude.
Como já respondi, sim, existe um operador ternário em python:
<expression 1> if <condition> else <expression 2>
Informação adicional:
Se <expression 1>
é a condição, você pode usar a avaliação de curto-circuito :
a = True
b = False
# Instead of this:
x = a if a else b
# You could use Short-cirquit evaluation:
x = a or b
PS: Obviamente, uma avaliação de curto-circuito não é um operador ternário, mas geralmente o ternário é usado nos casos em que o curto-circuito seria suficiente.
short-circuit
avaliação.
SIM, python tem um operador ternário, aqui está a sintaxe e um código de exemplo para demonstrar o mesmo :)
#[On true] if [expression] else[On false]
# if the expression evaluates to true then it will pass On true otherwise On false
a= input("Enter the First Number ")
b= input("Enter the Second Number ")
print("A is Bigger") if a>b else print("B is Bigger")
print
realmente não é uma boa escolha, pois isso dará um SyntaxError no Python2.
Python tem uma forma ternária para atribuições; no entanto, pode haver uma forma ainda mais curta da qual as pessoas devem estar cientes.
É muito comum precisar atribuir a uma variável um valor ou outro, dependendo de uma condição.
>>> li1 = None
>>> li2 = [1, 2, 3]
>>>
>>> if li1:
... a = li1
... else:
... a = li2
...
>>> a
[1, 2, 3]
^ Essa é a forma longa para realizar essas tarefas.
Abaixo está a forma ternária. Mas essa não é a maneira mais sucinta - veja o último exemplo.
>>> a = li1 if li1 else li2
>>>
>>> a
[1, 2, 3]
>>>
Com o Python, você pode simplesmente usar or
para atribuições alternativas.
>>> a = li1 or li2
>>>
>>> a
[1, 2, 3]
>>>
O acima funciona desde que li1
é None
e o interp trata isso como False em expressões lógicas. A interp então avança e avalia a segunda expressão, que não é None
e não é uma lista vazia - portanto, é atribuída a a.
Isso também funciona com listas vazias. Por exemplo, se você deseja atribuir a a
lista que tiver itens.
>>> li1 = []
>>> li2 = [1, 2, 3]
>>>
>>> a = li1 or li2
>>>
>>> a
[1, 2, 3]
>>>
Sabendo disso, você pode simplesmente executar tais tarefas sempre que as encontrar. Isso também funciona com strings e outros iterables. Você pode atribuir a a
sequência que não estiver vazia.
>>> s1 = ''
>>> s2 = 'hello world'
>>>
>>> a = s1 or s2
>>>
>>> a
'hello world'
>>>
Eu sempre gostei da sintaxe secundária, mas o Python dá um passo adiante!
Eu entendo que alguns podem dizer que essa não é uma boa escolha estilística, pois depende de mecânicas que não são imediatamente aparentes para todos os desenvolvedores. Pessoalmente, não concordo com esse ponto de vista. Python é uma linguagem rica em sintaxe, com muitos truques idiomáticos que não são imediatamente aparentes para o dabler. Mas quanto mais você aprende e entende a mecânica do sistema subjacente, mais você o aprecia.
Outras respostas falam corretamente sobre o operador ternário do Python. Eu gostaria de complementar mencionando um cenário para o qual o operador ternário é frequentemente usado, mas para o qual existe uma linguagem melhor. Este é o cenário do uso de um valor padrão.
Suponha que desejemos usar option_value
com um valor padrão, se não estiver definido:
run_algorithm(option_value if option_value is not None else 10)
ou simplesmente
run_algorithm(option_value if option_value else 10)
No entanto, uma solução cada vez melhor é simplesmente escrever
run_algorithm(option_value or 10)
se a variável estiver definida e você quiser verificar se ela possui valor, basta a or b
def test(myvar=None):
# shorter than: print myvar if myvar else "no Input"
print myvar or "no Input"
test()
test([])
test(False)
test('hello')
test(['Hello'])
test(True)
irá produzir
no Input
no Input
no Input
hello
['Hello']
True
x if x else y
, mas não x if z else y
.
Uma maneira elegante de encadear vários operadores:
f = lambda x,y: 'greater' if x > y else 'less' if y > x else 'equal'
array = [(0,0),(0,1),(1,0),(1,1)]
for a in array:
x, y = a[0], a[1]
print(f(x,y))
# Output is:
# equal,
# less,
# greater,
# equal
Eu acho difícil a sintaxe padrão do python val = a if cond else b
, às vezes faço isso:
iif = lambda (cond, a, b): a if cond else b
# so I can then use it like:
val = iif(cond, a, b)
Claro, ele tem a desvantagem de sempre avaliar os dois lados (aeb), mas a sintaxe é muito mais clara para mim
val = a if cond else b
declaração mais simples .
is_spacial=True if gender = "Female" else (True if age >= 65 else False)
**
pode ser aninhado conforme sua necessidade. boa sorte
**