入力として有効な値があるにもかかわらず、プログラムが「if」ステートメントの実行を拒否する

Aug 20 2020

私はコンピュータープログラミングにとても慣れておらず、現在PyCharm Communityでプログラムを書いています。このプログラムは、私の学校の生徒の名前が与えられると、学校からその生徒の家への道順を印刷します。

すべてが順調に進んでおり、昨夜はその基盤が機能しました。今日、コンピューターを開きましたが、何らかの理由で、プログラムが「if」/「elif」ステートメントの実行を拒否し、「if」/「elif」ステートメントを満たす値が指定されている場合でも、elseステートメントのみを実行します。

プログラムを書き直し、PyCharmを複数回再起動し、スペースとタブに一貫性があることを確認し、変数がすべて相互に通信できることを確認しました。私はここや他のウェブサイトでしばらく掘り下げましたが、昨日コードが機能していた理由がわかりませんが、elseステートメント以外の実行を拒否しています。

これが私のコードです。ユーザーに「どこに行きたいですか?」と尋ねます。その後、「家」の入力を受け取ります。これを受け取ると、方向を印刷します。これの代わりに、毎回 'else'ステートメントを実行します。

# Storing the names and directions of users:
David = "Directions to David's home from T... \n East on X, \n South on Y.," \
            " \n West on Z., \n South on A., \n first white house on the right."

Caroline = "Directions to Caroline's home from T... \n East on x, \n South on y.," \
        " \n East on z., \n South on p., \n East on q," \
        " \n West on t., \n last brick house in the cul-de-sac."

William = "Directions to Will's home from T... \n East on x, \n South on y.," \
        " \n West on z., \n South on Fa., \n West on b., \n first house on the right."

Bannon = "<Insert directions to Bannon's house>"

# User gives a specific name and then receives a location:
while True:
    destination = input("Where would you like to go? ")

    if destination.casefold() == 'Davids house':
        print(David)
        continue

    elif destination.casefold() == 'Carolines house':
        print(Caroline)
        continue

    elif destination.casefold() == 'Wills house':
        print(William)
        continue

    elif destination.casefold() == 'Bannons house':
        print(Bannon)
        continue

    # If an invalid location is given, this code will run:
    else:
        print("Sorry, that location wasn't found! Please try again.")
        continue

回答

2 mattbornski Aug 19 2020 at 23:50

casefold 文字列を小文字に変換し、参照文字列には大文字が含まれます。

簡単な修正として、「Davidshouse」を「davidshouse」などに変更できます。

長期的には、少し脆弱性の低い比較を実装することをお勧めしますが、これは大きな演習であり、プログラムの使用方法と解析の失敗の結果によって異なります。

2 marsnebulasoup Aug 20 2020 at 00:16

タイプミスの修正と、テストに違反することを行うユーザーのサポートについて、文字列の類似性の比較を使用して、入力がユーザーの名前に近いかどうかを判断する例を次に示します。

import difflib
# Storing the names and directions of users: 
#This is called a dictionary. More info here https://www.w3schools.com/python/python_dictionaries.asp
directions= {
    "David": "Directions to David's home from T... \n East on X, \n South on Y.," \
            " \n West on Z., \n South on A., \n first white house on the right.",

    "Caroline": "Directions to Caroline's home from T... \n East on x, \n South on y.," \
        " \n East on z., \n South on p., \n East on q," \
        " \n West on t., \n last brick house in the cul-de-sac.",

    "William":"Directions to Will's home from T... \n East on x, \n South on y.," \
        " \n West on z., \n South on Fa., \n West on b., \n first house on the right.",

    "Bannon":"<Insert directions to Bannon's house>"
}

# User gives a specific name and then receives a location:
while True:
    destination = input("Where would you like to go? ")

    highest = 0 #highest score between the user name and input
    user_key = "" #name of the user who most closely matches the input
    for user in directions: #iterate through all the user's names in the directions dictionary
      similarity = difflib.SequenceMatcher( #for each user's name, compare it to the input
          None, destination, user).ratio()
      if(similarity > highest): #if the similarity score is greater than the highest recorded score, update the score
        highest = similarity
        user_key = user
    
    #Code that runs if a match is too low are not found
    if(highest < 0.5): #adjust this based on how close you want the match to be. highest will always be between 0.0 and 1.0
      print("Sorry, that location wasn't found! Please try again.")
      continue

    #Print user's directions
    else:
      print('\n\nGetting directions to ' + user_key + '\'s house\n\n')
      print(directions[user_key] + "\n\n\n")

したがって、「ウィリアムの家」、「ウィリアム」、「ウィリアムの家」、「ウィリアム」、または「ウィリアム」に近いものを入力すると、ウィリアムの家への道順がわかります。

オンラインで実行する: https://repl.it/@marsnebulasoup/UprightMutedSymbol

1 tdelaney Aug 20 2020 at 00:06

プログラムを最小化してテストしてください!問題を実証するために必要以上のコードを投稿しました。if destination.casefold() == 'Davids house':動作しないような問題が発生したら、既定のデータに関する1つの問題を最小限に抑えます

destination = "david's house"
if not destination.casefold() == "Davids house":
    print(repr(destination), "failed")

このプリント

"david's house" failed

のヘルプは、ケースレス比較に適した文字列のバージョンを返すcasefoldと言っています。。ああ、それだけです。両側をケースフォールドする必要があります。そして、その厄介なアポストロフィがあります。アルファベット以外の文字を削除するなど、より正規化する必要があるかもしれません。

最小化することで、コードの適切なテストを作成しました。ケースフォールドやその他の正規化を行う小さな比較関数を作成できます。次に、その関数に対して12個のテストを記述して、すべてのエッジケースをテストできます。