El equivalente de Python de && (logical-and) en una declaración if

830

Aquí está mi 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

Recibo un error en el condicional IF .
¿Qué estoy haciendo mal?

Arsen Khachaturyan
fuente
10
Claramente Sergio quería saber por qué su código estaba roto, pero leí un poco más el título de la pregunta. ¿Por qué no estaría && disponible de todos modos? == y! = están disponibles (pero son diferentes de es y no es, lo sé). ¿Por qué no incluir esta sintaxis? ¿Preferencia personal?
physicsmichael
55
@ vgm64: ¿Por qué incluir una sintaxis redundante que no mejora un solo aspecto?
Konrad Rudolph
27
Me parece que el intérprete debería, en lugar de imprimir un "SyntaxError críptico: sintaxis no válida" críptico, detectar que el usuario ha usado &&y sugerirles que tal vez quieran usar la palabra clave and. Lo mismo ocurre con cosas como ++y otros operadores comunes de otros idiomas.
ArtOfWarfare
3
@physicsmichael "debería haber una, y preferiblemente solo una, forma obvia de hacerlo". import this
Nick T
3
@KonradRudolph Mejora absolutamente aspectos del lenguaje. Es más consistente e intuitivo para cualquiera que haya usado algún otro idioma. El hecho de que esta pregunta exista y tenga tanto tráfico como lo hace claramente resalta este problema como un punto de conflicto común para las personas.
jterm

Respuestas:

1473

Te gustaría en andlugar de &&.

ChristopheD
fuente
2
¿Qué debo hacer para esto: si x == 'n' e y == 'a' o y == 'b': <hacer algo> ¿Funcionará? @ChristopheD
diffracteD
77
@diffracteD: use paréntesis si desea anular la precedencia del operador estándar (que puede obtener información aquí: ibiblio.org/g2swap/byteofpython/read/operator-precedence.html )
ChristopheD
3
Me gusta que David Titarenco haya dado un ejemplo de
Alexx Roche
77
Llegué aquí después de que escribí ambos &&y ANDobtuve un error (no esperaba que Python quisiera la palabra en minúsculas and).
Xeoncross
2
Creo que deberías usar & See: stackoverflow.com/questions/36921951/…
user1761806
229

Python utiliza andy orcondicionales.

es decir

if foo == 'abc' and bar == 'bac' or zoo == '123':
  # do something
David Titarenco
fuente
55
No olvides que Python tampoco tiene (bueno, y!)
inspectorG4dget
99
¿Su ejemplo evalúa a "(si esto y esto) o eso" O "si esto y (esto o aquello)"?
Jeff
12
@ Jeff Tu primer camino. and tiene mayor prioridad que or.
Buge
1
@Buge parece que "o" está más arriba en la tabla que vinculó
Matt
55
@Matt la tabla va desde la precedencia más baja a la más alta. Es más fácil recordar la precedencia si has estudiado álgebra booleana; "o" es suma y "y" es multiplicación.
Michael Stroud
48

Recibo un error en el condicional IF. ¿Qué estoy haciendo mal?

La razón por la que obtienes un SyntaxErrores que no hay &&operador en Python. Del mismo modo ||y no! son operadores válidos de Python.

Algunos de los operadores que puede conocer de otros idiomas tienen un nombre diferente en Python. Los operadores lógicos &&y en ||realidad se llaman andy or. Del mismo modo, !se llama al operador de negación lógica not.

Entonces podrías escribir:

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

o incluso:

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

Alguna información adicional (que puede ser útil):

Resumí el operador "equivalentes" en esta tabla:

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

Consulte también la documentación de Python: 6.11. Operaciones booleanas .

Además de los operadores lógicos, Python también tiene operadores bit a bit / binarios:

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

No hay negación bit a bit en Python (solo el operador inverso bit a bit ~, pero eso no es equivalente a not).

Ver también 6.6. Operaciones aritméticas unitarias y bit a bit / binarias y 6.7. Operaciones aritméticas binarias .

Los operadores lógicos (como en muchos otros idiomas) tienen la ventaja de que están en cortocircuito. Eso significa que si el primer operando ya define el resultado, entonces el segundo operador no se evalúa en absoluto.

Para mostrar esto, uso una función que simplemente toma un valor, lo imprime y lo devuelve nuevamente. Esto es útil para ver qué se evalúa realmente debido a las declaraciones de impresión:

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

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

Como puede ver, solo se ejecuta una declaración de impresión, por lo que Python realmente ni siquiera miró el operando correcto.

Este no es el caso de los operadores binarios. Aquellos siempre evalúan ambos operandos:

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

Pero si el primer operando no es suficiente, entonces, por supuesto, se evalúa el segundo operador:

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

Para resumir esto aquí hay otra tabla:

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

El Truey Falserepresenta lo que bool(left-hand-side)regresa, no tienen que ser Trueo False, solo necesitan regresar Trueo Falsecuando boolse les solicite (1).

Entonces, en Pseudo-Code (!) Las funciones andy orfuncionan así:

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)

Tenga en cuenta que este es un pseudocódigo y no un código de Python. En Python no puede crear funciones llamadas ando orporque son palabras clave. Además, nunca debe usar "evaluar" o if bool(...).

Personalizando el comportamiento de tus propias clases

Este implícita boolllamada se puede utilizar para personalizar la forma en sus clases se comportan con and, ory not.

Para mostrar cómo se puede personalizar esto, uso esta clase, que nuevamente printes algo para rastrear lo que está sucediendo:

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)

Entonces, veamos qué sucede con esa clase en combinación con estos 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)

Si no tiene un __bool__método, Python también verifica si el objeto tiene un __len__método y si devuelve un valor mayor que cero. Puede ser útil saberlo en caso de que cree un contenedor de secuencia.

Ver también 4.1. Prueba de valor de verdad .

Matrices y subclases NumPy

Probablemente un poco más allá del alcance de la pregunta original, pero en caso de que esté lidiando con matrices o subclases NumPy (como Pandas Series o DataFrames), la boolllamada implícita aumentará el 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().

En estos casos, puede usar la lógica y la función de NumPy que realiza un elemento inteligente and(o 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])

Si se trata solo de matrices booleanas , también podría usar los operadores binarios con NumPy, estos realizan comparaciones de elementos (pero también binarios):

>>> 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 la boolllamada en los operandos tiene que regresar Trueo Falseno es completamente correcta. Es solo el primer operando que necesita devolver un booleano en su __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)

Esto se debe a que en andrealidad devuelve el primer operando si el primer operando se evalúa Falsey si se evalúa a Truecontinuación, devuelve el segundo operando:

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

Del mismo modo, orpero al revés:

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

Sin embargo, si los usa en una ifdeclaración if, también invocará implícitamente boolel resultado. Entonces, estos puntos más finos pueden no ser relevantes para usted.

MSeifert
fuente
36

Dos comentarios:

  • Uso andy orpara operaciones lógicas en Python.
  • Use 4 espacios para sangrar en lugar de 2. Se lo agradecerá más tarde porque su código se verá más o menos igual que el código de todos los demás. Ver PEP 8 para más detalles.
istruble
fuente
10

Utiliza andyor para realizar operaciones lógicas como en C, C ++. Como literalmente andes &&y ores|| .


Echa un vistazo a este divertido ejemplo,

Digamos que quieres construir puertas lógicas en Python:

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

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

Ahora intenta llamarlos:

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

Esto generará:

False
True

¡Espero que esto ayude!

geekidharsh
fuente
9

Fui con una solución 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:]
Gran rojo
fuente
77
Esta no es una respuesta a la pregunta real.
Matthew leyó el
5

Probablemente este no sea el mejor código para esta tarea, pero 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
fuente
-3

Un solo &(no doble &&) es suficiente o, como sugiere la respuesta principal, puede usar 'y'. También encontré esto en pandas

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

si reemplazamos "&" con "y", no funcionará.

William You
fuente
1
Solo y no cortocircuitará la expresión (lo que significa que ambos serán evaluados independientemente del valor de retorno de la primera expresión)
user528025
-4

quizás con & en cambio% es más rápido y mantiene la lectura

otras pruebas pares / impares

x es par? x% 2 == 0

x es impar? no x% 2 == 0

tal vez es más claro con bit a bit y 1

x es impar? x y 1

x es par? no x & 1 (no impar)

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

Uso de "y" en condicional. A menudo uso esto cuando importo en 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
fuente
14
Esta pregunta fue formulada y respondida hace casi 7 años. ¿Qué agrega su respuesta a esas respuestas que ya están aquí? En general, a menos que tenga algo sorprendentemente nuevo que decir, no debe agregar una nueva respuesta a una pregunta anterior, donde la edad se mide como varios años, cuando ya hay buenas respuestas disponibles.
Jonathan Leffler