Eu tenho um script python que pode receber zero ou três argumentos de linha de comando. (Ele é executado no comportamento padrão ou precisa dos três valores especificados.)
Qual é a sintaxe ideal para algo como:
if a and (not b or not c) or b and (not a or not c) or c and (not b or not a):
?
python
if-statement
Chris Wilson
fonte
fonte
len(sys.argv)
sempre será pelo menos 1: inclui o executável comoargv[0]
.if not (a and b and c)
(zero args) e depoisif a and b and c
(todos os três args)?Respostas:
Se você quer dizer um formulário mínimo, vá com isso:
O que traduz o título da sua pergunta.
UPDATE: como corretamente dito pela Volatility e Supr, você pode aplicar a lei de De Morgan e obter o equivalente:
Meu conselho é usar o formulário que for mais significativo para você e para outros programadores. O primeiro significa "há algo falso, mas também algo verdadeiro" , o segundo "há algo verdadeiro, mas não tudo" . Se eu otimizasse ou fizesse isso no hardware, escolheria o segundo, aqui, apenas o mais legível (também levando em consideração as condições que você testará e seus nomes). Eu escolhi o primeiro.
fonte
if not (a and b and c) and (a or b or c)
if (a or b or c) and not (a and b and c)
para combinar perfeitamente com o título;) #if any([a,b,c]) and not all([a,b,c])
E se:
Outra variante:
fonte
sum(conditions)
pode dar errado se algum deles retornar,2
por exemplo, o que éTrue
.sum(map(bool, conditions))
Essa pergunta já tinha muitas respostas altamente votadas e uma resposta aceita, mas todas elas até agora foram distraídas por várias maneiras de expressar o problema booleano e perderam um ponto crucial:
Essa lógica não deve ser de responsabilidade do seu código em primeiro lugar , mas deve ser manipulada por
argparse
módulo. Não se preocupe em escrever uma declaração if complexa, em vez disso, prefira configurar seu analisador de argumentos da seguinte forma:E sim, deve ser uma opção, não um argumento posicional, porque afinal é opcional .
editado: Para abordar a preocupação de LarsH nos comentários, abaixo está um exemplo de como você pode escrevê-lo se tiver certeza de que deseja a interface com 3 ou 0argumentos posicionais . Sou da opinião de que a interface anterior tem um estilo melhor, porqueargumentos opcionais devem ser opções , mas aqui está uma abordagem alternativa por uma questão de integridade. Observe o kwarg sobrescrito
usage
ao criar seu analisador, pois,argparse
caso contrário,será gerada automaticamente uma mensagem de uso enganosa!Aqui estão alguns exemplos de uso:
fonte
Eu iria para:
Eu acho que isso deve causar um curto-circuito com bastante eficiência
Explicação
Ao criar
conds
um iterador, o primeiro uso deany
entrará em curto-circuito e deixará o iterador apontando para o próximo elemento, se algum item for verdadeiro; caso contrário, consumirá toda a lista e seráFalse
. O próximoany
pega os itens restantes no iterável e garante que não existem outros valores verdadeiros ... Se houver, toda a declaração não pode ser verdadeira, portanto, não há um elemento único (portanto, curto-circuitos novamente). O últimoany
retornaráFalse
ou esgotará o iterável e o seráTrue
.nota: o acima verifica se apenas uma condição está definida
Se você deseja verificar se um ou mais itens, mas nem todos os itens estão definidos, pode usar:
fonte
[a, b, c] = [True, True, False]
seu código não "imprime"False
, enquanto o resultado esperado éTrue
?iter
.any
eall
consumirá preguiçosamente a lista, é verdade, mas a lista já foi completamente avaliada quando você chegar lá!A sentença em inglês:
Traduz para esta lógica:
A palavra "mas" geralmente implica uma conjunção, em outras palavras "e". Além disso, "todos eles" se traduz em uma conjunção de condições: essa condição e essa condição e outra condição. O "não" inverte toda a conjunção.
Eu não concordo que a resposta aceita. O autor deixou de aplicar a interpretação mais direta à especificação e deixou de aplicar a Lei de De Morgan para simplificar a expressão a menos operadores:
enquanto afirma que a resposta é uma "forma mínima".
fonte
Isso retorna
True
se uma e apenas uma das três condições forTrue
. Provavelmente o que você queria no seu código de exemplo.fonte
Que tal: (condição única)
Observe, se você permitir duas condições também, poderá fazer isso
fonte
1 <= bool(a) + bool(b) + bool(c) <= 2
.Para ser claro, você deseja tomar sua decisão com base em quanto dos parâmetros é TRUE lógico (no caso de argumentos de string - não está vazio)?
Então você tomou uma decisão:
Agora a lógica está mais clara.
fonte
E por que não apenas contá-los?
fonte
Se você não se importa em ser um pouco enigmático, pode simular o
0 < (a + b + c) < 3
que retornarátrue
se você tiver entre uma e duas declarações verdadeiras e false se todas forem falsas ou nenhuma for falsa.Isso também simplifica se você usar funções para avaliar os bools, pois apenas avalia as variáveis uma vez, o que significa que você pode escrever as funções em linha e não precisa armazenar temporariamente as variáveis. (Exemplo:.
0 < ( a(x) + b(x) + c(x) ) < 3
)fonte
A pergunta afirma que você precisa dos três argumentos (a e bec) ou nenhum deles (não (a ou b ou c))
Isto dá:
(a e bec) ou não (a ou b ou c)
fonte
Pelo que entendi, você tem uma função que recebe 3 argumentos, mas se não o fizer, será executada no comportamento padrão. Como você não explicou o que deve acontecer quando 1 ou 2 argumentos são fornecidos, assumirei que ele deve simplesmente executar o comportamento padrão. Nesse caso, acho que você encontrará a seguinte resposta muito vantajosa:
No entanto, se você deseja que 1 ou 2 argumentos sejam tratados de maneira diferente:
nota: Isso pressupõe que os
False
valores " " não serão passados para este método.fonte
Se você trabalha com um iterador de condições, pode ser lento o acesso. Mas você não precisa acessar cada elemento mais de uma vez e nem sempre precisa ler tudo. Aqui está uma solução que funcionará com geradores infinitos:
fonte
Quando todo dado
bool
éTrue
, ou quando todo dadobool
éFalse
...todos são iguais um ao outro!
Portanto, basta encontrar dois elementos que sejam avaliados para
bool
s diferentespara saber que há pelo menos um
True
e pelo menos umFalse
.Minha curta solução:
Eu acredito que curto-circuito, porque AFAIK
a==b==c
é iguala==b and b==c
.Minha solução generalizada:
Também escrevi um código que lida com várias iteráveis, mas a excluí daqui porque acho inútil. No entanto, ainda está disponível aqui .
fonte
Isso é basicamente uma funcionalidade "alguns (mas não todos)" (quando contrastada com as funções
any()
eall()
internas).Isso implica que deve haver
False
s eTrue
s entre os resultados. Portanto, você pode fazer o seguinte:Uma vantagem desse código é que você só precisa iterar uma vez pelos itens resultantes (booleanos).
Uma desvantagem é que todas essas expressões de verdade são sempre avaliadas e não causam curto-circuito como os operadores
or
/and
.fonte
.issuperset
que, em vez de apenas verificar o comprimento 2,bool
não é possível retornar nada além de Verdadeiro e Falso. Por que atribuir um lambda (leia-se: função anônima) a um nome em vez de apenas usar um def?return
se usardef
. Eu acho que a generalidade desta solução é boa. não é necessário nos restringir aos booleanos, a questão é essencialmente "como garantir que todos esses elementos ocorram na minha lista". por queset
se você não precisa da mutabilidade? mais imutabilidade é sempre melhor se você não precisar do desempenho.tee
itertools.tee
mas 1) eu estava procurando uma linha única que fosse simples / pequena o suficiente para garantir a cópia e a colagem, 2) você já deu uma resposta que usa essa técnica :-) #