Estou tentando aprender python e encontrei um código que é bom e curto, mas não faz totalmente sentido
o contexto era:
def fn(*args):
return len(args) and max(args)-min(args)
Eu entendo o que está fazendo, mas por que o python faz isso - ou seja, retorna o valor em vez de Verdadeiro / Falso?
10 and 7-2
retorna 5. Da mesma forma, alterar e para ou resultará em uma alteração na funcionalidade. assim
10 or 7 - 2
Voltaria 10.
Este é um estilo legítimo / confiável ou há alguma pegadinha nisso?
python
operators
logical-operators
Marcin
fonte
fonte
and
(bem comoor
) não está restrito a trabalhar ou retornar valores booleanos.None
ou uma exceção)0
você não poderá dizer seargs
estava vazio ou não, mas tinha todos os elementos iguais.Respostas:
TL; DR
Começamos resumindo os dois comportamentos dos dois operadores lógicos
and
eor
. Esses idiomas formarão a base de nossa discussão a seguir.O comportamento também está resumido nos documentos , especialmente nesta tabela:
O único operador que retorna um valor booleano, independentemente de seus operandos, é o
not
operador.Avaliações de "veracidade" e "verdadeiras"
A declaração
É uma maneira concisa (e possivelmente menos legível) muito
pythônicade dizer "seargs
não estiver vazio, retorne o resultado demax(args) - min(args)
", caso contrário, retorne0
. Em geral, é uma representação mais concisa de umaif-else
expressão. Por exemplo,Deve (aproximadamente) traduzir para:
Ou equivalente,
Similarmente,
É equivalente a,
Onde
exp1
eexp2
são objetos Python arbitrários ou expressões que retornam algum objeto. A chave para entender os usos dos operadores lógicosand
eor
aqui é entender que eles não estão restritos a operar ou retornar valores booleanos. Qualquer objeto com um valor de veracidade pode ser testado aqui. Isto incluiint
,str
,list
,dict
,tuple
,set
,NoneType
, e objectos utilizador definido. As regras de curto-circuito também se aplicam.Mas o que é verdade?
Refere-se a como os objetos são avaliados quando usados em expressões condicionais. @Patrick Haugh resume muito bem a verdade neste post .
Quão
and
funcionaNós construímos a pergunta do OP como uma segue para uma discussão sobre como esses operadores nesses casos.
Encontrar o mínimo e o máximo é fácil (use as funções integradas!). O único obstáculo aqui é lidar apropriadamente com o caso extremo em que a lista de argumentos pode estar vazia (por exemplo, chamar
foo()
). Podemos fazer ambos em uma única linha, graças aoand
operador:Uma vez que
and
é usada, a segunda expressão também deve ser avaliada se a primeira forTrue
. Observe que, se a primeira expressão for avaliada como verdadeira, o valor de retorno será sempre o resultado da segunda expressão . Se a primeira expressão for avaliada como Falsy, o resultado retornado será o resultado da primeira expressão.Na função acima, If
foo
recebe um ou mais argumentos,len(args)
é maior que0
(um número positivo), então o resultado retornado émax(args) - min(args)
. OTOH, se nenhum argumento é passado,len(args)
é0
que é Falsas e0
é devolvido.Observe que uma maneira alternativa de escrever esta função seria:
Ou, mais concisamente,
Claro, nenhuma dessas funções executa qualquer verificação de tipo, portanto, a menos que você confie completamente na entrada fornecida, não confie na simplicidade dessas construções.
Quão
or
funcionaEu explico o funcionamento de
or
uma maneira semelhante com um exemplo inventado.Usamos
or
para lidar com o caso de canto aqui. Nós definimosfoo
como:foo
executa uma filtragem na lista para reter todos os números9000
. Se existir algum desses números, o resultado da compreensão da lista é uma lista não vazia que é verdadeira, então ela é retornada (curto-circuito em ação aqui). Se não existirem tais números, então o resultado da lista comp[]
é Falsy. Portanto, a segunda expressão agora é avaliada (uma string não vazia) e é retornada.Usando condicionais, poderíamos reescrever esta função como,
Como antes, essa estrutura é mais flexível em termos de tratamento de erros.
fonte
if ... else (if ... else (if ... else (if ... else ...)))
pode muito bem ser reescrito... and ... and ... and ... and ...
e, nesse ponto, realmente se torna difícil argumentar a legibilidade para qualquer um dos casos.Citando do Python Docs
Então, é assim que o Python foi projetado para avaliar as expressões booleanas e a documentação acima nos dá uma ideia de por que eles fizeram isso.
Para obter um valor booleano, apenas faça um typecast.
Por quê?
Curto-circuito.
Por exemplo:
O mesmo vale para
or
também, ou seja, ele retornará a expressão que é Verdadeira assim que a encontrar, pois a avaliação do resto da expressão é redundante.Em vez de retornar hardcore
True
ouFalse
, Python retorna Truthy ou Falsey , que de qualquer forma serão avaliados emTrue
ouFalse
. Você pode usar a expressão como está e ela ainda funcionará.Para saber o que é Truthy e Falsey , verifique a resposta de Patrick Haugh
fonte
e e / ou executam lógica booleana, mas retornam um dos valores reais quando estão comparando. Ao usar e , os valores são avaliados em um contexto booleano da esquerda para a direita. 0, '', [], (), {} e None são falsos em um contexto booleano; tudo o mais é verdade.
Se todos os valores são verdadeiros em um contexto booleano, e retorna o último valor.
Se algum valor for falso em um contexto booleano e retornar o primeiro valor falso.
Então, o código
retorna o valor de
max(args)-min(args)
quando há args, senão ele retorna,len(args)
que é 0.fonte
Isso é legítimo, é uma avaliação de curto-circuito em que o último valor é retornado.
Você fornece um bom exemplo. A função retornará
0
se nenhum argumento for passado, e o código não precisa verificar um caso especial de nenhum argumento passado.Outra maneira de usar isso é definir como padrão os argumentos Nenhum para um primitivo mutável, como uma lista vazia:
Se algum valor não verdadeiro for passado para
alist
ele, o padrão é uma lista vazia, uma maneira útil de evitar umaif
instrução e a armadilha do argumento padrão mutávelfonte
Pegadinhas
Sim, existem algumas pegadinhas.
fn() == fn(3) == fn(4, 4)
Primeiro, se
fn
retorna0
, você não pode saber se foi chamado sem nenhum parâmetro, com um parâmetro ou com vários parâmetros iguais:O que isso
fn
significa?Então, Python é uma linguagem dinâmica. Não é especificado em lugar nenhum o que
fn
faz, como deve ser sua entrada e como deve ser sua saída. Portanto, é muito importante nomear a função corretamente. Da mesma forma, os argumentos não precisam ser chamadosargs
.delta(*numbers)
oucalculate_range(*numbers)
pode descrever melhor o que a função deve fazer.Erros de argumento
Finalmente, o
and
operador lógico deve evitar que a função falhe se chamada sem nenhum argumento. Ainda assim, ele falha se algum argumento não for um número:Possível alternativa
Esta é uma maneira de escrever a função de acordo com "Mais fácil pedir perdão do que permissão". princípio :
Como um exemplo:
Se você realmente não deseja lançar uma exceção quando
delta
é chamado sem nenhum argumento, você pode retornar algum valor que não seria possível de outra forma (por exemplo,-1
ouNone
):fonte
Gostaria de acrescentar a esta questão que não é apenas legítimo e confiável, mas também ultra prático. Aqui está um exemplo simples:
Portanto, você pode realmente usá-lo a seu favor. Para estar consciente é assim que eu vejo:
Or
operadorO
or
operador do Python retorna o primeiro valor Truth-y, ou o último valor, e paraAnd
operadorO
and
operador do Python retorna o primeiro valor False-y, ou o último valor, e paraPor trás das cenas
Em python, todos os números são interpretados como
True
exceto 0. Portanto, dizendo:é o mesmo que:
O que é claramente
False
. Portanto, é lógico que ele retorne 0fonte
Sim. Este é o comportamento correto de comparação.
Pelo menos em Python,
A and B
retornosB
seA
é essencialmenteTrue
incluindo, seA
não for nula, NÃONone
NÃO um recipiente vazio (tais como um vaziolist
,dict
, etc.).A
é retornado IFFA
é essencialmenteFalse
ouNone
ou Vazio ou Nulo.Por outro lado,
A or B
os retornosA
seA
é essencialmenteTrue
incluindo, seA
não for nula, NÃONone
NÃO um recipiente vazio (tais como um vaziolist
,dict
, etc.), caso contrário retornaB
.É fácil não notar (ou ignorar) esse comportamento porque, em Python, qualquer
non-null
objeto não vazio avaliado como True é tratado como um booleano.Por exemplo, todos os itens a seguir imprimirão "Verdadeiro"
Por outro lado, todos os itens a seguir imprimirão "Falso"
fonte
A
é essencialmenteTrue
. Corrigido.entender de maneira simples,
E:
if first_val is False return first_val else second_value
por exemplo:
mas,
e => se alguém for falso, será falso. se ambos forem verdadeiros, então só se tornará verdade
OU:
if first_val is False return second_val else first_value
A razão é, se primeiro for falso, ele verifica se 2 é verdadeiro ou não.
por exemplo:
mas,
ou => se alguém for falso, será verdadeiro. portanto, se o primeiro valor for falso, não importa quais valores 2 suponham ser. portanto, ele retorna o segundo valor, seja o que for.
se alguém for verdadeiro, então se tornará verdadeiro. se ambos forem falsos, então se tornará falso.
fonte