2013-03-22 11 views
6

Ho scritto questo bit di codice inutilmente complicato sul mio modo di imparare a utilizzare l'istruzione in per rendere le dichiarazioni if funzionanti meglio. Ho due domande che seguono lo snippet di codice.Le istruzioni "in" python restituiscono automaticamente true

answer = ['Yes', 'yes', 'YES'] 
answer2 = ['No', 'no', 'NO'] 
ans = raw_input() 
for i in range(0, 3): 
    if ans in answer[i]: 
     print "Yes!" 
    elif ans in answer2[i]: 
     print "No!" 
    else: 
     print "Don't know what that means" 

Prima domanda: Penso if n in listname: restituisce come True o False automaticamente. Qualcuno sa se è così?

Seconda domanda: il codice sopra riportato restituisce 3 righe che variano a seconda che lo ans sia effettivamente in answer o answer2. Ho cercato di eliminare che sostituendo le porzioni rilevanti in questo modo:

if ans in answer[i] == True:

Ciò ha avuto l'effetto di rendere strano il codice di uscita solo l'istruzione else:. Quindi qualcuno può spiegarmi la differenza tra come Python interpreta if ans in answer[i]: e if ans in answer[i] == True:, per favore?

risposta

5

Per quanto riguarda la differenza tra ans in answer[i] e ans in answer[i] == True, semplice: Python espande quest'ultima forma ad ans in answer[i] and answer[i] == True, che è, ovviamente, False poiché una stringa non è uguale a True.

Un esempio più semplice può aiutare illustrare questo:

>>> a = [1, 2, 3] 
>>> 2 in a 
True 
>>> 2 in a == True 
False 
>>> 2 in a and a == True 
False 
>>> (2 in a) == True 
True 
>>> 2 in a == [1, 2, 3] 
True 
>>> 2 in a and a == [1, 2, 3] 
True 

Notate come l'aggiunta di parentesi cambia il comportamento - questo è simile a espansioni come 1 < x < 5, al contrario di (1 < x) < 5.

Come nota a margine, è generalmente considerato di scarsa qualità per verificare esplicitamente per True o False - è molto meglio scrivere semplicemente if x in y.

15

Per rispondere alle tue domande in ordine inverso, il motivo per cui il confronto esplicito con True non ha funzionato per te è che Python non ha interpretato l'espressione come previsto. Il parser Python ha la gestione speciale di confrontare espressioni in modo che sia possibile concatenare insieme e ottenere un risultato ragionevole, in questo modo:

>>> "a" == "a" == "a" 
True 

noti che Python ha per il trattamento di tutta questa cosa come un'operazione, perché se lo dividi in due operazioni entrambi i casi non si ottiene lo stesso risultato:

>>> ("a" == "a") == "a" 
False 
>>> "a" == ("a" == "a") 
False 

Questi comportano in modo diverso perché la parte tra le parentesi viene valutata per prima e restituisce True, ma True != "a" così l'intera espressione restituisce false.

Per diritti, quanto sopra non dovrebbe avere alcun impatto sul programma. Purtroppo, Python gestisce in tramite lo stesso meccanismo == così quando si concatenano insieme questi vengono interpretati come una sequenza come sopra, in modo Python effettivamente valutata come segue:

>> "a" in ["a"] == True 
False 
>>> ("a" in ["a"]) and ("a" == True) 
False 

È folle e probabilmente intuitivo, ma questo è, purtroppo, solo come funziona.Per ottenere il comportamento che volevi è necessario utilizzare le parentesi per forzare Python per valutare la prima parte a parte:

>>> ("a" in ["a"]) == True 
True 

Con tutto ciò detto, il == True è ridondante, perché, come si sospetta, l'espressione restituisce già un valore booleano e l'istruzione if può solo valutarla così com'è.

Per tornare ora al tuo altro problema, credo che quello che stai cercando di fare è prendere una riga di input e produrre una riga di output corrispondente a seconda di ciò che l'utente ha inserito. È possibile applicare l'operatore in in una stringa e una lista per vedere se la stringa è nella lista, che permette di eliminare il ciclo for del tutto:

answer = ['Yes', 'yes', 'YES'] 
answer2 = ['No', 'no', 'NO'] 
ans = raw_input() 
if ans in answer: 
    print "Yes!" 
elif ans in answer2: 
    print "No!" 
else: 
    print "Don't know what that means" 

Questo primo test se l'ingresso corrisponde a qualsiasi delle stringhe in answer, quindi lo stesso per answer2. Naturalmente, è possibile ottenere un effetto simile ma anche supportare altre forme come YeS semplicemente convertendo l'input in minuscolo e confrontandolo con il formato minuscolo:

if ans.lower() == "yes": 
    print "Yes!" 
# (and so forth) 
Problemi correlati