質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

ただいまの
回答率

87.37%

ifを2つ以上使っていて、本来はelifを使うはずなのに、エラーが出ない

解決済

回答 3

投稿

  • 評価
  • クリップ 0
  • VIEW 991

score 55

じゃんけんのifの仕組みをしっかり理解したい。

じゃんけんを作るコードを練習として書いていました。それが以下です。

import random


hand_dict = {
    '1': 'グー',
    '2': 'チョキ',
    '3': 'パー'
}

print('手を入力してください')
print('1:グー 2:チョキ 3:パー')

player_input = input()

list = [1, 2, 3]
if int(player_input) not in list:
    print('入力が正しくありません。')
    exit()


else:
    player = hand_dict[player_input]
    print('入力した手: ' + player)


com_input = random.choice(['1', '2', '3'])

com = hand_dict[com_input]
print('コンピューターの手: ' + com)

print(player, 'VS', com,sep='')

if player == 'グー':
     if com == 'チョキ':
        print('あなたの勝ち')

     if com == 'パー':
        print('コンピューターの勝ち')

     if com == player:
        print('あいこ')

if player == 'チョキ':
    if com == 'パー':
        print('あなたの勝ち')

    if com == 'グー':
        print('コンピューターの勝ち')

    if com == player:
        print('あいこ')

if player == 'パー':
    if com == 'グー':
        print('あなたの勝ち')

    if com == 'チョキ':
        print('コンピューターの勝ち')

    if com == player:
        print('あいこ')

結果はなぜか正常に扱われました。

プレイヤーがだしてきたグーショキパーに対してcomの対応を決める際に、単純にifですべてつないでしまったのですが、本を見たらifを2つ以上つなげる時はelifを用いるとなっていました。ただし、入れ子ならばifのインデントの中に連続してifを入れることができるらしいです。
今回のコードでは並列してifを3つも使っているので、なぜ正しくコードが出力されたのかわかりません。
お分かりになられた方がいたら、ご教授お願いします。

一応、elifとelseをつかって書き直したのが以下で正しく動きました。

import random


hand_dict = {
    '1': 'グー',
    '2': 'チョキ',
    '3': 'パー'
}

print('手を入力してください')
print('1:グー 2:チョキ 3:パー')

player_input = input()

list = [1, 2, 3]
if int(player_input) not in list:
    print('入力が正しくありません。')
    exit()


else:
    player = hand_dict[player_input]
    print('入力した手: ' + player)


com_input = random.choice(['1', '2', '3'])

com = hand_dict[com_input]
print('コンピューターの手: ' + com)

print(player, 'VS', com,sep='')

if player == 'グー':
    if com == 'チョキ':
        print('あなたの勝ち')

    elif com == 'パー':
        print('コンピューターの勝ち')

    else:
        print('あいこ')

elif player == 'チョキ':
    if com == 'パー':
        print('あなたの勝ち')

    elif com == 'グー':
        print('コンピューターの勝ち')

    else:
        print('あいこ')

else:
    if com == 'グー':
        print('あなたの勝ち')

    elif com == 'チョキ':
        print('コンピューターの勝ち')

    else:
        print('あいこ')

ifとelifの使い分け

  • 気になる質問をクリップする

    クリップした質問は、後からいつでもマイページで確認できます。

    またクリップした質問に回答があった際、通知やメールを受け取ることができます。

    クリップを取り消します

  • 良い質問の評価を上げる

    以下のような質問は評価を上げましょう

    • 質問内容が明確
    • 自分も答えを知りたい
    • 質問者以外のユーザにも役立つ

    評価が高い質問は、TOPページの「注目」タブのフィードに表示されやすくなります。

    質問の評価を上げたことを取り消します

  • 評価を下げられる数の上限に達しました

    評価を下げることができません

    • 1日5回まで評価を下げられます
    • 1日に1ユーザに対して2回まで評価を下げられます

    質問の評価を下げる

    teratailでは下記のような質問を「具体的に困っていることがない質問」、「サイトポリシーに違反する質問」と定義し、推奨していません。

    • プログラミングに関係のない質問
    • やってほしいことだけを記載した丸投げの質問
    • 問題・課題が含まれていない質問
    • 意図的に内容が抹消された質問
    • 過去に投稿した質問と同じ内容の質問
    • 広告と受け取られるような投稿

    評価が下がると、TOPページの「アクティブ」「注目」タブのフィードに表示されにくくなります。

    質問の評価を下げたことを取り消します

    この機能は開放されていません

    評価を下げる条件を満たしてません

    評価を下げる理由を選択してください

    詳細な説明はこちら

    上記に当てはまらず、質問内容が明確になっていない質問には「情報の追加・修正依頼」機能からコメントをしてください。

    質問の評価を下げる機能の利用条件

    この機能を利用するためには、以下の事項を行う必要があります。

回答 3

checkベストアンサー

+2

プレイヤーがだしてきたグーショキパーに対してcomの対応を決める際に、単純にifですべてつないでしまったのですが、本を見たらifを2つ以上つなげる時はelifを用いるとなっていました。

正しくは、『elifを使うと効率が良い場合がある』ですかね。

num = 0

if num == 0:   # 条件を判定して、真なら実行
    ...                  

if num == 1:   # 条件を判定して、真なら実行
    ...        #         
num = 0

if num == 0:   # 条件を判定して、真なら実行
    ...            

elif num == 1: # 直前のif文の中身が実行されたならスキップ、
               # そうでないなら条件を判定して、真なら実行
    ...

また、条件に依っては挙動が異なることもあります。

num = 15
if num % 3 == 0:
    print('3の倍数')

if num % 5 == 0:
    print('5の倍数')
num = 15
if num % 3 == 0:
    print('3の倍数')

elif num % 5 == 0:
    print('5の倍数')

実行結果を予想してから、実際に試してみると良いでしょう。

ただし、入れ子ならばifのインデントの中に連続してifを入れることができるらしいです。

入れ子であるかどうかは関係ないです。
これについて参考書に間違いがあるとはちょっと考えづらいので、誤読していると思います。

今回のコードでは並列してifを3つも使っているので、なぜ正しくコードが出力されたのかわかりません。

効率的かはともかく、間違っているわけでは全く無いから。

おまけ

elifやelseを使うメリットが無い場合もあります。
例えば、しばしばこんなコードを目にしますが、個人的にはちょっと冗長に思えます。

def is_aho(num): 
    """3の倍数か3の付く数値なら真を返す"""
    if num % 3 == 0:
        print('3の倍数')
        return True
    elif '3' in str(num):
        print('3が付く数')
        return True
    else:
        return False 

次のように書き換えられます。

def is_aho(num): 
    """3の倍数か3の付く数値なら真を返す"""
    if num % 3 == 0:   
        print('3の倍数')
        return True

    # ここに来ている時点で3の倍数で無いことは確定
    if '3' in str(num):   
        print('3が付く数')
        return True 

    # ここに来ている時点で、直前の二条件を満たさないことは確定
    return False 

投稿

編集

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2019/01/23 22:39

    回答ありがとうございます。
    なるほど、モヤモヤしていたifとelifの使い分けがきちんとわかりました。
    わかりやすい例としてのコードもわかりやすかったです。理解に役立ちました。
    ありがとうございました。

    キャンセル

  • 2019/01/23 23:00

    ご指摘ありがとうございます。教科書をもう一度読んでみます。
    おまけ、ありがとうございます。時と場合に応じて適切にできるよう意識していきます。

    キャンセル

+1

条件が同時には成立しない(排他的)な場合は、処理結果はどちらも同じです。
単純なケースを書くと、

if x > 0:
  print("正")
if x < 0:
  print("負")

if x > 0:
  print("正")
elif x < 0:
  print("負")


正の時に、x < 0の演算をするかどうかの違いがあります。

投稿

編集

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2019/01/23 22:37

    回答ありがとうございます。
    なるほど、ということは、今回のじゃんけんの条件コードは対他的な条件設定だったため、結果は同じになったのですね。
    理解できました。ありがとうございました。

    キャンセル

  • 2019/01/23 22:40

    if x > 0:

    if y > 0:
    と、
    if x > 0:

    elif y > 0:
    は大きく違います。

    キャンセル

  • 2019/01/23 22:58

    なるほど、自分の理解が正しければ、後者はx > 0が成り立った時点で y >0はもう行わない、ということですよね。勉強になります。

    キャンセル

0

5 つの勝敗判定方法を書いてみました。

judge_0 は質問文にあるような、全パターンを if で処理しています。
judge_1 は、 else をつかって 比較処理をすこし減らしています。
judge_2 は、さらに手の比較処理を減らしています。
それぞれの方法での比較処理回数の平均を計算してみてください。

judge_3 は if でなく、表を引くようにしています。
表を引くには内部で値の比較処理をしているはずですが、プログラムコード上のは if での比較ロジックは現れません。

judge_4 は、ジャンケンのルールを数値での演算処理に変換したものです。
勝敗判定結果から表示文字をつくる部分には Hash 表をつかっていますが、勝敗判定は数値演算だけで処理しています。

import random

# if だけで 9 通りを判定
def judge_0(com, human):
    if human == 'グー':
        if com == 'チョキ':
            print('あなたの勝ち')
        if com == 'パー':
            print('コンピューターの勝ち')
        if com == human:
            print('あいこ')
    if human == 'チョキ':
        if com == 'パー':
            print('あなたの勝ち')
        if com == 'グー':
            print('コンピューターの勝ち')
        if com == 'チョキ':
            print('あいこ')
    if human == 'パー':
        if com == 'グー':
            print('あなたの勝ち')
        if com == 'チョキ':
            print('コンピューターの勝ち')
        if com == 'パー':
            print('あいこ')

# if elif else9 通りを判定
def judge_1(com, human):
    if human == 'グー':
        if com == 'チョキ':
            print('あなたの勝ち')
        elif com == 'パー':
            print('コンピューターの勝ち')
        else:
            print('あいこ')
    elif human == 'チョキ':
        if com == 'パー':
            print('あなたの勝ち')
        elif com == 'グー':
            print('コンピューターの勝ち')
        else:
            print('あいこ')
    else:
        if com == 'グー':
            print('あなたの勝ち')
        elif com == 'チョキ':
            print('コンピューターの勝ち')
        else:
            print('あいこ')

# あいこ と 勝ち の条件を列挙して判定
def judge_2(com, human):
    if com == human:
        print('あいこ')
    elif ((human == 'グー' and com == 'チョキ') or
        (human == 'チョキ' and com == 'パー') or
        (human == 'パー' and com == 'グー')):
        print('あなたの勝ち')
    else:
        print('コンピューターの勝ち')

JUDGE_TABLE = {
    'グー':   {'グー': 0, 'チョキ': 1, 'パー': -1},
    'チョキ': {'グー': -1, 'チョキ': 0, 'パー': 1},
    'パー':   {'グー': 1, 'チョキ': -1, 'パー': 0}
}
MESSAGES = {
    -1: 'コンピューターの勝ち',
    0: 'あいこ',
    1: 'あなたの勝ち'
}
# 勝敗表を引いて判定
def judge_3(com, human):
    print(MESSAGES[JUDGE_TABLE[human][com]])

MESSAGES_X = {
    0: 'あいこ',
    1: 'あなたの勝ち',
    2: 'コンピューターの勝ち'
}
# 数値演算で判定
def judge_4(com, human):
    print(MESSAGES_X[(com + 3 - human) % 3])

hand_dict = {
    '1': 'グー',
    '2': 'チョキ',
    '3': 'パー'
}
enable_hands = list(hand_dict.keys())

# for human_input in enable_hands:
#    human = hand_dict[human_input]
#    for com_input in enable_hands:
#        com = hand_dict[com_input]
#        print(human, 'VS', com)
#        judge_0(com, human)
#        judge_1(com, human)
#        judge_2(com, human)
#        judge_3(com, human)
#        judge_4(int(com_input), int(human_input))

while True:
    print('手を入力してください')
    print('1:グー 2:チョキ 3:パー')

    human_input = input()
    if human_input not in enable_hands:
        print('入力が正しくありません。終了します。')
        break

    human = hand_dict[human_input]
    print('入力した手: ' + human)

    com_input = random.choice(enable_hands)
    com = hand_dict[com_input]
    print('コンピューターの手: ' + com)

    print(human, 'VS', com,sep='')
    judge_0(com, human)
    judge_1(com, human)
    judge_2(com, human)
    judge_3(com, human)
    judge_4(int(com_input), int(human_input))

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

15分調べてもわからないことは、teratailで質問しよう!

  • ただいまの回答率 87.37%
  • 質問をまとめることで、思考を整理して素早く解決
  • テンプレート機能で、簡単に質問をまとめられる

関連した質問

同じタグがついた質問を見る