O equivalente do Python a && (logic-and) em uma instrução if

830

Aqui está o meu código:

def front_back(a, b):
  # +++your code here+++
  if len(a) % 2 == 0 && len(b) % 2 == 0:
    return a[:(len(a)/2)] + b[:(len(b)/2)] + a[(len(a)/2):] + b[(len(b)/2):] 
  else:
    #todo! Not yet done. :P
  return

Estou recebendo um erro no condicional IF .
O que estou fazendo errado?

Arsen Khachaturyan
fonte
10
Claramente, Sergio queria saber por que seu código foi quebrado, mas eu li um pouco mais sobre o título da pergunta. Por que o && não estaria disponível de qualquer maneira? == e! = estão disponíveis (mas são diferentes de é e não é, eu sei). Por que não incluir esta sintaxe? Preferência pessoal?
physicsmichael
5
@ vgm64: Por que incluir sintaxe redundante que não melhora um único aspecto?
Konrad Rudolph
27
Parece-me que o intérprete deve, em vez de imprimir um "SyntaxError: sintaxe inválida" - detectar que o usuário usou &&e sugerir que eles possam querer usar a palavra-chave and. O mesmo vale para coisas como ++e outros operadores comuns de outros idiomas.
ArtOfWarfare 26/09
3
@physicsmichael "deve haver uma e, de preferência, apenas uma maneira óbvia de fazer isso". import this
Nick T
3
@KonradRudolph Melhora absolutamente aspectos da linguagem. É mais consistente e intuitivo para quem já usou outro idioma. o fato de que essa pergunta existe e tem tanto tráfego quanto destaca claramente esse problema como um ponto de discórdia comum para as pessoas.
jterm

Respostas:

1473

Você gostaria em andvez de &&.

ChristopheD
fonte
2
o que devo fazer para isso: se x == 'n' e y == 'a' ou y == 'b': <faça alguma coisa> Funcionará! @ChristopheD
diffracteD
7
@diffracteD: Use parênteses se você deseja substituir a precedência de operador padrão (que você pode aprender sobre aqui: ibiblio.org/g2swap/byteofpython/read/operator-precedence.html )
ChristopheD
3
Gosto que David Titarenco deu um corte-n-colar exemplo
Alexx Roche
7
Cheguei aqui depois de digitar os dois &&e ANDobtive um erro (não esperando que o python desejasse a palavra em minúscula and).
Xeoncross
2
Eu acho que você deveria usar & See: stackoverflow.com/questions/36921951/… #
user1761806
229

Python usa ande orcondicionais.

ie

if foo == 'abc' and bar == 'bac' or zoo == '123':
  # do something
David Titarenco
fonte
5
Não se esqueça que python também não tem (bem, e!)
inspectorG4dget
9
Seu exemplo avalia como "(se isso e isso) ou que" OU "se isso e (isso ou aquilo)"?
19414 Jeff
12
@ Jeff Sua primeira maneira. and tem precedência mais alta que or.
Buge
1
@Buge parece que "ou" é mais acima na tabela que é ligada
Matt
5
@Matt a tabela passa da precedência mais baixa para a mais alta. É mais fácil lembrar a precedência se você estudou álgebra booleana; "ou" é adição e "e" é multiplicação.
Michael Stroud
48

Estou recebendo um erro no condicional IF. O que estou fazendo errado?

A razão pela qual você obtém um SyntaxErroré que não há &&operador no Python. Da mesma forma ||e não! são operadores Python válidos .

Alguns dos operadores que você conhece de outros idiomas têm um nome diferente no Python. Os operadores lógicos &&e ||são realmente chamados ande or. Da mesma forma, o operador de negação lógica !é chamado not.

Então você pode escrever:

if len(a) % 2 == 0 and len(b) % 2 == 0:

ou até:

if not (len(a) % 2 or len(b) % 2):

Algumas informações adicionais (que podem ser úteis):

Resumi o operador "equivalentes" nesta tabela:

+------------------------------+---------------------+
|  Operator (other languages)  |  Operator (Python)  |
+==============================+=====================+
|              &&              |         and         |
+------------------------------+---------------------+
|              ||              |         or          |
+------------------------------+---------------------+
|              !               |         not         |
+------------------------------+---------------------+

Veja também a documentação do Python: 6.11. Operações booleanas .

Além dos operadores lógicos, o Python também possui operadores bit a bit / binários:

+--------------------+--------------------+
|  Logical operator  |  Bitwise operator  |
+====================+====================+
|        and         |         &          |
+--------------------+--------------------+
|         or         |         |          |
+--------------------+--------------------+

Não há negação bit a bit no Python (apenas o operador inverso bit a bit ~- mas isso não é equivalente a not).

Veja também 6.6. Operações aritméticas unárias e bit a bit / binárias e 6.7. Operações aritméticas binárias .

Os operadores lógicos (como em muitos outros idiomas) têm a vantagem de estar em curto-circuito. Isso significa que se o primeiro operando já define o resultado, o segundo operador não é avaliado.

Para mostrar isso, uso uma função que simplesmente pega um valor, imprime e retorna novamente. Isso é útil para ver o que é realmente avaliado devido às instruções de impressão:

>>> def print_and_return(value):
...     print(value)
...     return value

>>> res = print_and_return(False) and print_and_return(True)
False

Como você pode ver, apenas uma instrução de impressão é executada; portanto, o Python nem sequer olhou para o operando certo.

Este não é o caso dos operadores binários. Aqueles sempre avaliam os dois operandos:

>>> res = print_and_return(False) & print_and_return(True);
False
True

Mas se o primeiro operando não for suficiente, é claro que o segundo operador será avaliado:

>>> res = print_and_return(True) and print_and_return(False);
True
False

Para resumir isso, aqui está outra tabela:

+-----------------+-------------------------+
|   Expression    |  Right side evaluated?  |
+=================+=========================+
| `True` and ...  |           Yes           |
+-----------------+-------------------------+
| `False` and ... |           No            |
+-----------------+-------------------------+
|  `True` or ...  |           No            |
+-----------------+-------------------------+
| `False` or ...  |           Yes           |
+-----------------+-------------------------+

O Truee Falserepresenta o que bool(left-hand-side)retorna, eles não precisam ser Trueou False, eles apenas precisam retornar Trueou Falsequando boolsão chamados (1).

Portanto, no pseudo-código (!), As funções ande orfuncionam assim:

def and(expr1, expr2):
    left = evaluate(expr1)
    if bool(left):
        return evaluate(expr2)
    else:
        return left

def or(expr1, expr2):
    left = evaluate(expr1)
    if bool(left):
        return left
    else:
        return evaluate(expr2)

Note que este é pseudo-código e não código Python. No Python, você não pode criar funções chamadas andou orporque são palavras-chave. Além disso, você nunca deve usar "avaliar" ou if bool(...).

Customizando o comportamento de suas próprias classes

Essa boolchamada implícita pode ser usada para personalizar como suas classes se comportam and, ore not.

Para mostrar como isso pode ser personalizado, eu uso essa classe, que printé outra coisa para rastrear o que está acontecendo:

class Test(object):
    def __init__(self, value):
        self.value = value

    def __bool__(self):
        print('__bool__ called on {!r}'.format(self))
        return bool(self.value)

    __nonzero__ = __bool__  # Python 2 compatibility

    def __repr__(self):
        return "{self.__class__.__name__}({self.value})".format(self=self)

Então, vamos ver o que acontece com essa classe em combinação com esses operadores:

>>> if Test(True) and Test(False):
...     pass
__bool__ called on Test(True)
__bool__ called on Test(False)

>>> if Test(False) or Test(False):
...     pass
__bool__ called on Test(False)
__bool__ called on Test(False)

>>> if not Test(True):
...     pass
__bool__ called on Test(True)

Se você não possui um __bool__método, o Python também verifica se o objeto possui um __len__método e se ele retorna um valor maior que zero. Isso pode ser útil saber caso você crie um contêiner de sequência.

Veja também 4.1. Teste do valor da verdade .

Matrizes e subclasses NumPy

Provavelmente um pouco além do escopo da pergunta original, mas no caso de você estar lidando com matrizes ou subclasses NumPy (como Pandas Series ou DataFrames), a boolchamada implícita aumentará o temido ValueError:

>>> import numpy as np
>>> arr = np.array([1,2,3])
>>> bool(arr)
ValueError: The truth value of an array with more than one element is ambiguous. Use a.any() or a.all()
>>> arr and arr
ValueError: The truth value of an array with more than one element is ambiguous. Use a.any() or a.all()

>>> import pandas as pd
>>> s = pd.Series([1,2,3])
>>> bool(s)
ValueError: The truth value of a Series is ambiguous. Use a.empty, a.bool(), a.item(), a.any() or a.all().
>>> s and s
ValueError: The truth value of a Series is ambiguous. Use a.empty, a.bool(), a.item(), a.any() or a.all().

Nesses casos, você pode usar a lógica e a função do NumPy, que executa um elemento and(ou or):

>>> np.logical_and(np.array([False,False,True,True]), np.array([True, False, True, False]))
array([False, False,  True, False])
>>> np.logical_or(np.array([False,False,True,True]), np.array([True, False, True, False]))
array([ True, False,  True,  True])

Se você está lidando apenas com matrizes booleanas, também pode usar os operadores binários com o NumPy, eles realizam comparações entre elementos (mas também binárias):

>>> np.array([False,False,True,True]) & np.array([True, False, True, False])
array([False, False,  True, False])
>>> np.array([False,False,True,True]) | np.array([True, False, True, False])
array([ True, False,  True,  True])

(1)

Que a boolchamada aos operandos deve retornar Trueou Falsenão está completamente correta. É apenas o primeiro operando que precisa retornar um booleano em seu __bool__método:

class Test(object):
    def __init__(self, value):
        self.value = value

    def __bool__(self):
        return self.value

    __nonzero__ = __bool__  # Python 2 compatibility

    def __repr__(self):
        return "{self.__class__.__name__}({self.value})".format(self=self)

>>> x = Test(10) and Test(10)
TypeError: __bool__ should return bool, returned int
>>> x1 = Test(True) and Test(10)
>>> x2 = Test(False) and Test(10)

Isso porque, andna verdade, retorna o primeiro operando se o primeiro operando for avaliado Falsee, se for avaliado True, retornará o segundo operando:

>>> x1
Test(10)
>>> x2
Test(False)

Da mesma forma, ormas apenas o contrário:

>>> Test(True) or Test(10)
Test(True)
>>> Test(False) or Test(10)
Test(10)

No entanto, se você usá-los em uma ifdeclaração if, também implicitamente chamará boolo resultado. Portanto, esses pontos mais delicados podem não ser relevantes para você.

MSeifert
fonte
36

Dois comentários:

  • Use ande orpara operações lógicas em Python.
  • Use 4 espaços para recuar em vez de 2. Você agradecerá a si mesmo mais tarde, porque seu código será praticamente o mesmo que o código de todos os outros. Veja PEP 8 para mais detalhes.
istruble
fonte
10

Você usa andeor executa operações lógicas como em C, C ++. Como literalmente andé &&e oré|| .


Dê uma olhada neste exemplo divertido,

Digamos que você queira criar Logic Gates em Python:

def AND(a,b):
    return (a and b) #using and operator

def OR(a,b):
    return (a or b)  #using or operator

Agora tente ligar para eles:

print AND(False, False)
print OR(True, False)

Isso produzirá:

False
True

Espero que isto ajude!

geekidharsh
fonte
9

Eu fui com uma solução puramente matemática:

def front_back(a, b):
  return a[:(len(a)+1)//2]+b[:(len(b)+1)//2]+a[(len(a)+1)//2:]+b[(len(b)+1)//2:]
Big Red
fonte
7
Esta não é uma resposta para a pergunta real.
Mateus Leia
5

Provavelmente, esse não é o melhor código para esta tarefa, mas está funcionando -

def front_back(a, b):

 if len(a) % 2 == 0 and len(b) % 2 == 0:
    print a[:(len(a)/2)] + b[:(len(b)/2)] + a[(len(a)/2):] + b[(len(b)/2):]

 elif len(a) % 2 == 1 and len(b) % 2 == 0:
    print a[:(len(a)/2)+1] + b[:(len(b)/2)] + a[(len(a)/2)+1:] + b[(len(b)/2):] 

 elif len(a) % 2 == 0 and len(b) % 2 == 1:
     print a[:(len(a)/2)] + b[:(len(b)/2)+1] + a[(len(a)/2):] + b[(len(b)/2)+1:] 

 else :
     print a[:(len(a)/2)+1] + b[:(len(b)/2)+1] + a[(len(a)/2)+1:] + b[(len(b)/2)+1:]
Nasimuddin Ansari
fonte
-3

Um simples &(não o dobro &&) é suficiente ou, como a resposta principal sugere, você pode usar 'e'. Eu também achei isso em pandas

cities['Is wide and has saint name'] = (cities['Population'] > 1000000) 
& cities['City name'].apply(lambda name: name.startswith('San'))

se substituirmos o "&" por "e", ele não funcionará.

William You
fonte
1
Única e não
provoca um
-4

talvez com & em vez% seja mais rápido e mantenha a legibilidade

outros testes pares / ímpares

x é par? x% 2 == 0

x é ímpar? não x% 2 == 0

talvez seja mais claro com bit a bit e 1

x é ímpar? x & 1

x é par? não x & 1 (não ímpar)

def front_back(a, b):
    # +++your code here+++
    if not len(a) & 1 and not len(b) & 1:
        return a[:(len(a)/2)] + b[:(len(b)/2)] + a[(len(a)/2):] + b[(len(b)/2):] 
    else:
        #todo! Not yet done. :P
    return
Wirefall
fonte
-4

Uso de "e" em condicional. Costumo usar isso ao importar no Jupyter Notebook:

def find_local_py_scripts():
    import os # does not cost if already imported
    for entry in os.scandir('.'):
        # find files ending with .py
        if entry.is_file() and entry.name.endswith(".py") :
            print("- ", entry.name)
find_local_py_scripts()

-  googlenet_custom_layers.py
-  GoogLeNet_Inception_v1.py
Uki D. Lucas
fonte
14
Esta pergunta foi feita e respondida quase 7 anos atrás. O que sua resposta adiciona às respostas que já estão aqui? Em geral, a menos que você tenha algo surpreendentemente novo a dizer, não deve adicionar uma nova resposta a uma pergunta antiga - onde a idade é medida como vários anos - quando já existem boas respostas disponíveis.
Jonathan Leffler