2013-03-05 2 views
2

Я пытаюсь изучить Python, и я наткнулся на эту невероятно странную аномалию, программируя «викторину» для своих собственных целей обучения. Логическая «или» функция действует немного странно. Вот фрагмент кода:«или» не функционирует так, как должно быть в Python

def answercheck(answer): 
    solved = 0 
    while solved == 0: 
     useranswer = raw_input("> ") 
     if useranswer == answer: 
      solved = 1 
      correct() 
     elif useranswer == "A" or "B" or "C" or "D": 
      solved = 1 
      incorrect() 
     else: 
      print "False input. Try again." 

Вот что происходит. Функция answercheck вызывается с реальным ответом в качестве аргумента после того, как вопрос о викторине будет распечатан для участника викторины. Затем пользователю предлагается ответить. Поскольку я хочу, чтобы единственными действительными ответами были «A», «B», «C» или «D», я поставил это в цикле «while».

Итак, я подозреваю, что если кто-то сделал «useranswer» что-то бесполезное, как «lol» через raw_input, он будет снова запрашивать пользователя до тех пор, пока «A», «B», «C» или «D» не будут вставлены как ответ. Однако он не принимает и не отвечает ни на один ответ, который не является «ответом» как неправильным.

Так что я переписал вещь немного, и это, кажется, работает, когда я делаю это:

def answercheck(answer): 
    solved = 0 
    while solved == 0: 
     useranswer = raw_input("> ") 
     if useranswer == answer: 
      solved = 1 
      correct() 
     elif useranswer == "A": 
      solved = 1 
      incorrect() 
     elif useranswer == "B": 
      solved = 1 
      incorrect() 
     elif useranswer == "C": 
      solved = 1 
      incorrect() 
     elif useranswer == "D": 
      solved = 1 
      incorrect() 
     else: 
      print "False input. Try again." 

Это кажется немного излишним для меня. Что происходит в первом скрипте?

+0

'или' выражение, а не функция. –

+0

Это не так, как 'или' работает -' или 'берет левую сторону и правую сторону и возвращает' True', если обе стороны оценивает значение «True». То, что вы написали, имеет смысл на английском языке, но не на Python. –

+1

_or_ не является традиционным булевым оператором. Он оценивает первый элемент, где bool (item) == True. Так что _'fred 'или' jane'_ 'является' fred 'и _None или' jane'_ 'является' jane '. С переменными, _x = None; у = «джан»; print x или y_ prints 'jane'. – tdelaney

ответ

3

or работает на двух логических переменных; он не создает набор альтернативных вариантов. Попробуйте это:

useranswer == "A" or useranswer == "B" or useranswer == "C" or useranswer == "D" 

Или еще удобнее:

useranswer in ("A", "B", "C", "D") 

или даже

useranswer in "ABCD" 
+1

Спасибо! Этот ответ мне больше всего понравился. Спасибо кому-то еще. –

4

Правильный синтаксис для useranswer является любой из "A", "B", "C" или "D" является:

elif useranswer in ("A", "B", "C", "D"): 

или (если ваша версия Python достаточно недавнее, чтобы поддержать набор литералов):

elif useranswer in {"A", "B", "C", "D"}: 

Теперь у вас есть синтаксически действительный, но имеет совершенно другое значение.

+1

Или, оптимально, используйте набор: 'useranswer в {" A "," B "," C "," D "}:'. Это будет немного лучше, так как проверка принадлежности к набору будет 'O (1)' в отличие от 'O (n)' для кортежа. Это не будет иметь большого значения в большинстве ситуаций, но это хорошая привычка. –

+0

@ Lattyware: Хорошее предложение, спасибо! – NPE

+1

@Lattyware - за исключением этого конкретного случая, когда набор занимает в два раза длинный кортеж. Попробуйте 'timeit.timeit ('useranswer in (" A "," B "," C "," D ")', 'useranswer =" D "', number = 10000000)/10000000' vs' timeit.timeit (' useranswer в {"A", "B", "C", "D"} ',' useranswer = "D" ', number = 10000000)/10000000' vs 'timeit.timeit (' useranswer in" ABCD "', 'useranswer = "D",', число = 10000000)/10000000'. 'O (1)' не идет быстрее, чем 'O (n)' для каждого возможного ввода. Он работает быстрее для каждого достаточно большого ввода. –

1

useranswer == "A" or "B" or "C" or "D" означает

(((useranswer == "A") or "B") or "C") or "D" 

Вот почему он не работает, как вам нравится

+0

Это на самом деле отвечает, почему исходный синтаксис не работает. –

1

Оператор предшествования - Он оценивает useranswer == 'A' в любой другой, а затем "B", "C", «D» всегда оценивается как «True»

Вам необходимо сделать что-то вроде этого «

if useranswer in ['A', 'B', 'C', 'D']: 
    ... 
Смежные вопросы