Equivalente di Python di && (logico-e) in un'istruzione if


830

Ecco il mio codice:

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

Ricevo un errore nel condizionale IF .
Che cosa sto facendo di sbagliato?


10
Chiaramente Sergio voleva sapere perché il suo codice era rotto, ma ho letto un po 'di più nel titolo della domanda. Perché && non sarebbe comunque disponibile? == e! = sono disponibili (ma sono diversi da è e non lo sono, lo so). Perché non includere questa sintassi? Preferenza personale?
Physicsmichael,

5
@ vgm64: Perché includere la sintassi ridondante che non migliora un singolo aspetto?
Konrad Rudolph,

27
Mi sembra che l'interprete dovrebbe, piuttosto che stampare un "SintassiErrore: sintassi non valida", rilevare che l'utente ha usato &&e suggerire loro che potrebbero voler usare la parola chiave and. Lo stesso vale per cose come ++e altri operatori comuni di altre lingue.
ArtOfWarfare il

3
@physicsmichael "dovrebbe esserci un modo, e preferibilmente solo uno, ovvio per farlo." import this
Nick T,

3
@KonradRudolph Migliora assolutamente gli aspetti del linguaggio. È più coerente e intuitivo per chiunque abbia mai usato qualsiasi altra lingua. il fatto che questa domanda esista e abbia tanto traffico quanto evidenzia chiaramente questo problema come un punto critico comune per le persone.
jterm,

Risposte:


1473

Vorresti andinvece di &&.


2
cosa devo fare per questo: se x == 'n' e y == 'a' o y == 'b': <fare qualcosa> Funzionerà!? @ChristopheD
diffracteD

7
@diffracteD: utilizzare le parentesi se si desidera sovrascrivere la precedenza dell'operatore standard (di cui è possibile consultare qui: ibiblio.org/g2swap/byteofpython/read/operator-precedence.html )
ChristopheD,

3
Mi piace il fatto che David Titarenco abbia dato un esempio
incisivo

7
Sono arrivato qui dopo aver digitato entrambi &&e ANDho ricevuto un errore (non mi aspettavo che Python volesse la parola minuscola and).
Xeoncross,

2
Penso che si dovrebbe usare e da vedere: stackoverflow.com/questions/36921951/...
user1761806

229

Usi ande orcondizioni di Python .

vale a dire

if foo == 'abc' and bar == 'bac' or zoo == '123':
  # do something

5
Non dimenticare che anche Python non ha (beh, e!)
inspectorG4dget

9
Il tuo esempio valuta "(se questo e questo) o quel" OR "se questo e (questo o quello)"?
Jeff,

12
@Jeff Il tuo primo modo. and ha una precedenza maggiore di or.
Buge,

1
@Buge sembra che "o" sia più in alto nella tabella che hai collegato
Matt,

5
@Matt la tabella passa dalla precedenza più bassa alla più alta. È più facile ricordare la precedenza se hai studiato l'algebra booleana; "o" è addizione e "e" è moltiplicazione.
Michael Stroud,

48

Ricevo un errore nel condizionale IF. Che cosa sto facendo di sbagliato?

La ragione per cui si ottiene a SyntaxErrorè che non esiste un &&operatore in Python. Allo stesso modo ||e non! sono operatori Python validi .

Alcuni degli operatori che potresti conoscere da altre lingue hanno un nome diverso in Python. Gli operatori logici &&e ||sono effettivamente chiamati ande or. Allo stesso modo !viene chiamato l' operatore di negazione logicanot .

Quindi potresti semplicemente scrivere:

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

o anche:

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

Alcune informazioni aggiuntive (che potrebbero tornare utili):

Ho riassunto gli operatori "equivalenti" in questa tabella:

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

Vedi anche la documentazione di Python: 6.11. Operazioni booleane .

Oltre agli operatori logici, Python ha anche operatori bit a bit / binari:

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

Non c'è negazione bit a bit in Python (solo l'operatore inverso bit a bit ~- ma ciò non equivale a not).

Vedi anche 6.6. Operazioni aritmetiche unarie e bit a bit / binarie e 6.7. Operazioni aritmetiche binarie .

Gli operatori logici (come in molte altre lingue) hanno il vantaggio di essere in cortocircuito. Ciò significa che se il primo operando definisce già il risultato, il secondo operatore non viene valutato affatto.

Per mostrarlo uso una funzione che prende semplicemente un valore, lo stampa e lo restituisce di nuovo. Questo è utile per vedere cosa viene effettivamente valutato a causa delle dichiarazioni di stampa:

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

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

Come puoi vedere, viene eseguita una sola istruzione di stampa, quindi Python non ha nemmeno guardato l'operando giusto.

Questo non è il caso degli operatori binari. Questi valutano sempre entrambi gli operandi:

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

Ma se il primo operando non è sufficiente, ovviamente viene valutato il secondo operatore:

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

Per riassumere, ecco un'altra tabella:

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

Il Truee Falserappresentano ciò che bool(left-hand-side)ritorna, non devono essere Trueo False, devono solo tornare Trueo Falsequando boolviene chiamato su di loro (1).

Quindi in Pseudo-Code (!) Le funzioni ande orfunzionano in questo modo:

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)

Si noti che questo è pseudo-codice non codice Python. In Python non è possibile creare funzioni chiamate ando orperché queste sono parole chiave. Inoltre non dovresti mai usare "valutare" o if bool(...).

Personalizzare il comportamento delle tue classi

Questa implicita boolchiamata può essere utilizzato per personalizzare come le vostre classi si comportano con and, ore not.

Per mostrare come questo può essere personalizzato, uso questa classe che di nuovo printè qualcosa per tenere traccia di ciò che sta accadendo:

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)

Quindi vediamo cosa succede con quella classe in combinazione con questi operatori:

>>> 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 non hai un __bool__metodo, Python verifica anche se l'oggetto ha un __len__metodo e se restituisce un valore maggiore di zero. Potrebbe essere utile sapere nel caso in cui si crea un contenitore di sequenze.

Vedi anche 4.1. Test del valore di verità .

Array e sottoclassi di NumPy

Probabilmente un po 'oltre lo scopo della domanda originale ma nel caso in cui si tratti di array o sottoclassi di NumPy (come Pandas Series o DataFrames), la boolchiamata implicita aumenterà il temuto 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().

In questi casi puoi usare la logica e la funzione di NumPy che esegue un elemento 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])

Se hai a che fare solo con array booleani puoi anche usare gli operatori binari con NumPy, questi eseguono confronti a livello di elementi (ma anche binari):

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

Che la boolchiamata sugli operandi debba tornare Trueo che Falsenon sia completamente corretta. È solo il primo operando che deve restituire un valore booleano nel suo __bool__metodo:

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)

Questo perché in andrealtà restituisce il primo operando se il primo operando valuta Falsee se valuta Truequindi restituisce il secondo operando:

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

Allo stesso modo per oril contrario:

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

Tuttavia, se li si utilizza in ifun'istruzione, ifverrà anche implicitamente richiamato boolil risultato. Quindi questi punti più fini potrebbero non essere rilevanti per te.


36

Due commenti:

  • Utilizzare ande orper operazioni logiche in Python.
  • Usa 4 spazi per rientrare invece di 2. Ti ringrazierai più tardi perché il tuo codice sarà praticamente uguale al codice di tutti gli altri. Vedi PEP 8 per maggiori dettagli.

10

Si utilizza andeor per eseguire operazioni logiche come in C, C ++. Come letteralmente andè &&ed orè|| .


Dai un'occhiata a questo divertente esempio,

Supponiamo che tu voglia costruire Logic Gates in Python:

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

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

Ora prova a chiamarli:

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

Questo produrrà:

False
True

Spero che sia di aiuto!


9

Sono andato con una soluzione puramente matematica:

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

7
Questa non è una risposta alla domanda reale.
Matteo Leggi il

5

Probabilmente questo non è il miglior codice per questa attività, ma funziona -

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

-3

Un singolo &(non doppio &&) è sufficiente o come la risposta in alto suggerisce che puoi usare 'e'. Ho anche trovato questo nei panda

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

se sostituiamo "&" con "e", non funzionerà.


1
Individua e non cortocircuita l'espressione (ovvero entrambi verranno valutati indipendentemente dal valore restituito della prima espressione)
user528025

-4

forse con & invece% è più veloce e mantiene la leggibilità

altri test pari / dispari

x è pari? x% 2 == 0

x è dispari? non x% 2 == 0

forse è più chiaro con bitwise e 1

x è dispari? x & 1

x è pari? non x & 1 (non dispari)

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

-4

Uso di "e" in condizionale. Lo uso spesso durante l'importazione in 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

14
Questa domanda è stata posta e ha risposto quasi 7 anni fa. Cosa aggiunge la tua risposta a quelle risposte che sono già qui? In generale, a meno che tu non abbia qualcosa di sorprendentemente nuovo da dire, non dovresti aggiungere una nuova risposta a una vecchia domanda - dove vecchio viene misurato come più anni - quando ci sono già buone risposte già disponibili.
Jonathan Leffler,
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.