Python supporta il corto circuito?


Risposte:



192

Il cortocircuito comportamento in operator and, or:

Definiamo innanzitutto una funzione utile per determinare se qualcosa viene eseguito o meno. Una semplice funzione che accetta un argomento, stampa un messaggio e restituisce l'input, invariato.

>>> def fun(i):
...     print "executed"
...     return i
... 

Si può osservare il comportamento cortocircuitando Python di and, oroperatori nel seguente esempio:

>>> fun(1)
executed
1
>>> 1 or fun(1)    # due to short-circuiting  "executed" not printed
1
>>> 1 and fun(1)   # fun(1) called and "executed" printed 
executed
1
>>> 0 and fun(1)   # due to short-circuiting  "executed" not printed 
0

Nota: i seguenti valori sono considerati dall'interprete come falsi:

        False    None    0    ""    ()    []     {}

Comportamento in corto circuito in funzione: any(), all():

Python any()eall() funzioni supportano anche il corto circuito. Come mostrato nei documenti; valutano ogni elemento di una sequenza in ordine, fino a trovare un risultato che consenta un'uscita anticipata nella valutazione. Considera gli esempi seguenti per capirli entrambi.

La funzione any()controlla se qualche elemento è True. Termina l'esecuzione non appena viene rilevato un True e restituisce True.

>>> any(fun(i) for i in [1, 2, 3, 4])   # bool(1) = True
executed
True
>>> any(fun(i) for i in [0, 2, 3, 4])   
executed                               # bool(0) = False
executed                               # bool(2) = True
True
>>> any(fun(i) for i in [0, 0, 3, 4])
executed
executed
executed
True

La funzione all()controlla che tutti gli elementi siano True e interrompe l'esecuzione non appena viene rilevato un False:

>>> all(fun(i) for i in [0, 0, 3, 4])
executed
False
>>> all(fun(i) for i in [1, 0, 3, 4])
executed
executed
False

Comportamento in corto circuito nel confronto incatenato:

Inoltre, in Python

I confronti possono essere concatenati arbitrariamente ; per esempio, x < y <= zequivale a x < y and y <= z, tranne che yviene valutato solo una volta (ma in entrambi i casi znon viene valutato affatto quando x < yviene trovato falso).

>>> 5 > 6 > fun(3)    # same as:  5 > 6 and 6 > fun(3)
False                 # 5 > 6 is False so fun() not called and "executed" NOT printed
>>> 5 < 6 > fun(3)    # 5 < 6 is True 
executed              # fun(3) called and "executed" printed
True
>>> 4 <= 6 > fun(7)   # 4 <= 6 is True  
executed              # fun(3) called and "executed" printed
False
>>> 5 < fun(6) < 3    # only prints "executed" once
executed
False
>>> 5 < fun(6) and fun(6) < 3 # prints "executed" twice, because the second part executes it again
executed
executed
False

Modifica:
Un altro punto interessante da notare : - Logico and, glior operatori in Python restituiscono il valore di un operando anziché un valore booleano ( Trueo False). Per esempio:

L'operazione x and ydà il risultatoif x is false, then x, else y

A differenza di altre lingue &&, ad esempio , gli ||operatori in C che restituiscono 0 o 1.

Esempi:

>>> 3 and 5    # Second operand evaluated and returned 
5                   
>>> 3  and ()
()
>>> () and 5   # Second operand NOT evaluated as first operand () is  false
()             # so first operand returned 

Allo stesso modo, l' oroperatore return ha lasciato il valore più alto per il quale bool(value)== Truealtrimenti il ​​valore più falso (in base al comportamento di cortocircuito), esempi:

>>> 2 or 5    # left most operand bool(2) == True
2    
>>> 0 or 5    # bool(0) == False and bool(5) == True
5
>>> 0 or ()
()

Quindi, come è utile? Un esempio di utilizzo fornito in Practical Python di Magnus Lie Hetland:
supponiamo che un utente debba inserire il proprio nome, ma potrebbe scegliere di non inserire nulla, nel qual caso si desidera utilizzare il valore predefinito '<unknown>'. Puoi usare un'istruzione if, ma puoi anche affermare le cose in modo molto succinto:

In [171]: name = raw_input('Enter Name: ') or '<Unkown>'
Enter Name: 

In [172]: name
Out[172]: '<Unkown>'

In altre parole, se il valore restituito da raw_input è vero (non una stringa vuota), viene assegnato al nome (non cambia nulla); in caso contrario, '<unknown>'viene assegnato il valore predefinito name.


1
Minori cavilli: l'elenco esplicito di valori falsi è leggermente fuorviante. Qualsiasi tipo può avere uno o più valori falsi. Per convenzione, tutti i tipi numerici con valore 0sono falsy (quindi non è solo 0, è 0.0, 0j, decimal.Decimal(0), fractions.Fraction(0), etc.), come lo sono tutte le collezioni di lunghezza 0(così in cima a quello che avete elencato, b''[PY3], u''[PY2] e set()/ frozenset()sono tutti i built-in che valutano come falsi), ma i tipi definiti dall'utente / di terze parti possono definire i propri (con __bool__[Py3] / __nonzero__[Py2] direttamente o indirettamente definendo __len__).
ShadowRanger,

@ShadowRanger qui il tuo commento completerà la mia risposta. grazie per aver aggiunto questa nota.
Grijesh Chauhan,

Inoltre, Python valuta due volte i condizionali in cortocircuito, se in seguito usati come booleani ... a meno che non siano in un'istruzione if, che è privatizzata
Erik Aronesty

48

Sì. Prova quanto segue nell'interprete Python:

e

>>>False and 3/0
False
>>>True and 3/0
ZeroDivisionError: integer division or modulo by zero

o

>>>True or 3/0
True
>>>False or 3/0
ZeroDivisionError: integer division or modulo by zero
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.