странное поведение в python, если предложение

Я написал простую маленькую игру «камень, ножницы, бумага» на питоне, и у меня возникли некоторые трудности с предложением if, вот соответствующий код:

def play():
    user = str(input("rock, paper or scissors? Choose one: "))
    print("You chose", user)

    if user == "paper" or "Paper":
        paper()

    elif user == "rock" or "Rock":
        rock()

    elif user == "scissors" or "Scissors":
        scissors()

    else:
        print("Sorry, your choice was not valid, try again please.")
        play()

Теперь, независимо от того, выбирал ли я камень, ножницы или бумагу, это всегда вызывало первое условие, приводя меня к функции бумаги. На самом деле я уже решил это, это было второе условие, которое я поставил в предложениях if, «Бумага», «Камень» и «Ножницы», которые я поставил там для людей, делающих первую букву в верхнем регистре. Мой вопрос: почему второе условие вызвало первое предложение if? Когда я удалил все вторые струны, все заработало отлично, камень вызвал второе условие, ножницы - третье и так далее. Надеюсь, это не слишком запутанно. Спасибо.


person Peter Goldsborough    schedule 24.06.2013    source источник
comment
На самом деле это дубликат десятков эквивалентных вопросов. Жаль, что их так трудно искать.   -  person abarnert    schedule 25.06.2013
comment
Этот вопрос появлялся так много раз раньше на SO. Если бы люди сделали свои заголовки более описательными, другие люди смогли бы извлечь пользу из их вопросов и ответов. Вместо странного поведения ... может быть, «или» всегда возвращает true в выражении python if. Это, скорее всего, будет плодотворным для будущих поисков Google.   -  person SethMMorton    schedule 25.06.2013
comment
Какое название может быть более полезным? Я тогда поменяю. Прости за это.   -  person Peter Goldsborough    schedule 25.06.2013


Ответы (6)


user == "paper" or "Paper"

всегда верно. Оператор or проверяет выражения по обе стороны от себя, и если одно из них истинно, результат or также является истинным. Ваш тест выше проверяет (до) две вещи:

  • Верно ли выражение user == "paper"? Если это так, то все выражение истинно, поэтому не проверяйте вторую часть, потому что True or x всегда истинно независимо от значения x.
  • Верно ли выражение "Paper"? А поскольку в Python строки ненулевой длины истинны, эта часть всегда истинна.

Таким образом, даже если первая часть ложна, вторая часть всегда истинна, поэтому выражение в целом всегда истинно.

Вы хотели что-то вроде этого:

user == "paper" or user == "Paper"

или, еще лучше:

user in ("paper", "Paper")

или, лучше всего:

user.lower() == "paper"
person kindall    schedule 24.06.2013

Вы также можете сделать это со списками и in:

if user in ["paper", "Paper"]:
    paper()

или используя регулярное выражение:

import re
user = 'paper'
if re.match('papers?', user):
    paper()
elif re.match('[Rr]ock', user):
    rock()

с регулярными выражениями вы также можете выполнять совпадение без учета регистра:

import re
user = 'paper'
if re.match('papers?', user, re.I):
    paper()

который будет соответствовать всем: paper, Paper, PaperS, ...

person perreal    schedule 24.06.2013

ты хочешь:

if user == "paper" or user == "Paper":

То же самое и для других.

Если вы просто положите

if "Paper":

Python оценивает его как if this_value_is_true. То же самое с кодом, который у вас есть, в основном оценивается как «если пользовательская переменная равна« бумаге »или True», что всегда будет верно.

person Cfreak    schedule 24.06.2013

Кажется, я знаю, откуда взялась ваша проблема:

if user == "paper" or user == "Paper":

Это должно решить проблему

person Kevin Klute    schedule 24.06.2013

Этот:

if user == "paper" or "Paper":

… анализируется следующим образом:

if (user == "paper") or "Paper":

Если user на самом деле равно "paper", это if True or "Paper", то есть True.

В противном случае это if False or "Paper", то есть "Paper".

Поскольку True и "Paper" оба правдивы, if всегда происходит.

person abarnert    schedule 24.06.2013

if user == "paper" or "Paper":

На самом деле оценивает:

(user == "paper")  or "Paper"

то есть (результат пользователя == "бумага") или "Бумага"

Итак, здесь 2 возможности:

  1. Правда или "бумага"
  2. Ложный или «бумажный»

В первом случае он возвращает True, а во втором — "Paper".

Поскольку «Бумага» является значением True (все непустые строки равны True), поэтому это условие всегда равно True.

Вы должны использовать:

if user.lower() == "paper"
person Ashwini Chaudhary    schedule 24.06.2013
comment
Я не думаю, что user == "paper" оценивается как user == True. Скорее, user == "paper" верно, когда user равно "paper". - person A.E. Drew; 25.06.2013
comment
@A.E.Drew о! это была опечатка, исправил. - person Ashwini Chaudhary; 25.06.2013