Uma linha se atribuição de condição


140

eu tenho o seguinte código

num1 = 10
someBoolValue = True

Eu preciso definir o valor de num1para 20se someBoolValueé True; e não faça nada de outra maneira. Então, aqui está o meu código para isso

num1 = 20 if someBoolValue else num1

Existe alguma maneira de evitar a ...else num1parte para torná-la mais limpa? Um equivalente a

if someBoolValue:
    num1 = 20

Eu tentei substituindo-o ...else passassim: num1=20 if someBoolValue else pass. Tudo o que recebi foi erro de sintaxe. Nem eu poderia simplesmente omitir a ...else num1parte.


2
Apenas mude tudo para num1 = 20 if someBoolValue else 10. Então você salva a num1=10linha também?
Thomas Ahle

Obrigado. Mas este não é exatamente o meu código. Eu quis dizer que num1já existe ...
bdhar

Respostas:


196

Eu não acho que isso seja possível no Python, pois o que você realmente está tentando fazer provavelmente se expande para algo assim:

num1 = 20 if someBoolValue else num1

Se você excluir else num1, receberá um erro de sintaxe, pois tenho certeza de que a atribuição deve realmente retornar algo.

Como outros já mencionaram, você pode fazer isso, mas é ruim porque provavelmente acabará se confundindo ao ler esse pedaço de código da próxima vez:

if someBoolValue: num1=20

Eu não sou um grande fã do num1 = someBoolValue and 20 or num1mesmo pela mesma razão. Na verdade, tenho que pensar duas vezes no que essa linha está fazendo.

A melhor maneira de realmente conseguir o que você quer fazer é a versão original:

if someBoolValue:
    num1 = 20

A razão pela qual é a melhor versão é porque é muito óbvio o que você quer fazer e não se confunde, ou quem mais entrará em contato com esse código posteriormente.

Além disso, como nota lateral, num1 = 20 if someBoolValueé válido o código Ruby, porque o Ruby funciona de maneira um pouco diferente.


8
De acordo com o PEP-308 ( docs.python.org/2.5/whatsnew/pep-308.html ), a expressão condicional pode ser esclarecida se colocada em parênteses, como em num1 = (20 if someBoolValue else num1).
haridsv

46

Usa isto:

num1 = 20 if someBoolValue else num1

3
isto é o que eu tenho usado .. e procurando uma alternativa .. obrigado mesmo assim !!
bdhar

Como chamar esse bloco? Quero dizer, como é o nome?
fuat

1
é um operador ternário #
Chris Maes

Não se deve usar essa abordagem se estiver percorrendo grandes conjuntos de dados, pois ela introduz uma atribuição desnecessária caso terminemos na instrução else.
dapc 12/12/19

21

Em uma linha:

if someBoolValue: num1 = 20

Mas não faça isso. Esse estilo normalmente não é esperado. As pessoas preferem a forma mais longa para maior clareza e consistência.

if someBoolValue:
    num1 = 20

(Igualmente, as tampas de camelo devem ser evitadas. Portanto, use some_bool_value.)

Observe que uma expressão em linha some_value if predicatesem elseparte não existe porque não haveria um valor de retorno se o predicado fosse falso. No entanto, as expressões devem ter um valor de retorno claramente definido em todos os casos. Isso é diferente do uso, como em, por exemplo, Ruby ou Perl.


2
Porque fica difícil ler e você provavelmente ficará confuso com seu próprio código, e isso nunca é uma boa ideia.
Frost

@bdhar, por que você quer colocá-lo em uma linha? Não vai correr mais rápido, será apenas mais difícil para outras pessoas lerem
John La Rooy 24/10

1
@gnibbler, sem motivo, na verdade. eu estava procurando uma forma mais curta com melhor legibilidade ..
bdhar

17

você pode usar um dos seguintes:

(falseVal, trueVal)[TEST]

TEST and trueVal or falseVal

1
Atribuição condicional agradável de um liner
minhas23

Como é chamada essa "estrutura"? Eu nunca vi isso em ~ 6 meses aprendendo Python.
Guimoute 31/07

1
Pelo menos essas não são atribuições, a menos que você as coloque na frente delas e, segundo, elas não funcionarão da maneira descrita aqui. O primeiro cria uma tupla e escolhe um de seus elementos pelo índice. Ele funcionará apenas para testes que retornam um número inteiro entre -1 e 1, ou True/ False, uma vez que boolé uma subclasse de int. Em todos os casos em que o teste retorna algo que apenas avaliaria true, ele falha com uma exceção. O segundo funciona apenas desde trueValque não avalie o próprio falso, o que resultaria em ser falseValatribuído mesmo que o teste fosse verdadeiro.
Bachsau

é bem curto, mas também muito complicado com segurança ser usado como "padrão recomendado", veja acima comentário de Bachsau ... (assim que eu downvoted-lo)
tverrbjelke

6

Não. Acho que você esperava que algo assim num1 = 20 if someBoolValuefuncionasse, mas não funciona. Eu acho que a melhor maneira é com a ifdeclaração como você a escreveu:

if someBoolValue:
    num1 = 20

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

Essa é a minha nova resposta final. A resposta anterior foi a seguinte e foi um exagero para o problema declarado. Getting_too_clever == not Good. Aqui está a resposta anterior ... ainda é boa se você quiser adicionar uma coisa para Truecond e outra para False:

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

Você mencionou num1já teria um valor que deveria ser deixado em paz. Presumi num1 = 10que essa é a primeira declaração do post, então a operação a ser realizada 20é adicionar 10.

num1 = 10
someBoolValue = True

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

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

produziu essa saída

num1 = 20
someBoolValue = True

Agora estou pensando que eu deveria ter respondido 'num1 = 10 + 10 * (someBoolValue == True)' Problema definido como a condição 'False' como basicamente não-operacional. Se for necessário adicionar um valor diferente para 'False', a resposta anterior será melhor. Eu edito minha postagem ou faço isso nos comentários?
MikeyB


2

Se você deseja invocar um método se algum valor booleano for verdadeiro, pode colocar else Nonepara finalizar o trinary.

>>> 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

Se um código de linha definitivamente vai acontecer para você, o Python 3.8 apresenta expressões de atribuição afetuosamente conhecidas como "o operador da morsa".

:=

someBoolValue and (num := 20)

A 20será atribuído numse a primeira expressão booleana é True. A atribuição deve estar entre parênteses aqui, caso contrário, você receberá um erro de sintaxe.

num = 10
someBoolValue = True

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

num = 10
someBoolValue = False

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

0

Para o futuro viajante do tempo do google, aqui está uma nova maneira (disponível no python 3.8 em diante):

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

Você pode definitivamente usar num1 = (20 se someBoolValue else num1) se desejar.


Duplicata das respostas acima?
Adam Smith

-1

Aqui está o que eu posso sugerir. Use outra variável para derivar a cláusula if e atribua-a a num1.

Código:

num2 =20 if someBoolValue else num1
num1=num2


-1

Você pode fazer assim.

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

Você pode resolver seu problema dessa maneira, mas usar 'try / except block' não é a melhor prática para python.

Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.