【问题标题】:Getting the Value returned from a Loop to print() only once仅将循环返回的值获取到 print() 一次
【发布时间】:2019-01-22 23:11:09
【问题描述】:

当尝试检索第二个选项的解密密码时,无论输入的网站是否真实,我都无法阻止程序打印Does Not Compute。当它不真实时它会打印两次,所以这让我相信它正在打印for i in the range(len(passwords)),即 2。

如何让它只打印一次密码或Does Not Compute 而不再重复它?我正在尝试检查输入是否等于网站,但它仍然会重复打印两次。

import csv
import sys

# The password list - We start with it populated for testing purposes
passwords = [["yahoo", "XqffoZeo"], ["google", "CoIushujSetu"]]
# The password file name to store the passwords to
passwordFileName = "samplePasswordFile"
# The encryption key for the caesar cypher
encryptionKey = 16
# Caesar Cypher Encryption
def passwordEncrypt(unencryptedMessage, key):
    # We will start with an empty string as our encryptedMessage
    encryptedMessage = ""
    # For each symbol in the unencryptedMessage we will add an encrypted symbol into the encryptedMessage
    for symbol in unencryptedMessage:
        if symbol.isalpha():
            num = ord(symbol)
            num += key
            if symbol.isupper():
                if num > ord("Z"):
                    num -= 26
                elif num < ord("A"):
                    num += 26
            elif symbol.islower():
                if num > ord("z"):
                    num -= 26
                elif num < ord("a"):
                    num += 26
            encryptedMessage += chr(num)
        else:
            encryptedMessage += symbol
    return encryptedMessage


def loadPasswordFile(fileName):
    with open(fileName, newline="") as csvfile:
        passwordreader = csv.reader(csvfile)
        passwordList = list(passwordreader)
    return passwordList


def savePasswordFile(passwordList, fileName):
    with open(fileName, "w+", newline="") as csvfile:
        passwordwriter = csv.writer(csvfile)
        passwordwriter.writerows(passwordList)


prompt_msg = """
What would you like to do:
 1. Open password file
 2. Lookup a password
 3. Add a password
 4. Save password file
 5. Print the encrypted password list (for testing)
 6. Quit program
Please enter a number (1-4)
"""

while True:
    print(prompt_msg)
    choice = input()

    if choice == "1":  # Load the password list from a file
        passwords = loadPasswordFile(passwordFileName)

    elif choice == "2":  # Lookup at password
        print("Which website do you want to lookup the password for?")
        for keyvalue in passwords:
            print(keyvalue[0])
        print("----")
        passwordToLookup = input()
        for i in range(len(passwords)):
            print(f"i={i}, store_info={passwords[i]}, website={passwords[i][0]}")
            if passwordToLookup == passwords[i][0]:
                password = passwordEncrypt(passwords[i][1], -(encryptionKey))
                print(f"=> The password is {password}.")
            else:
                print("=> Does not compute!")

    elif choice == "3":
        print("What website is this password for?")
        website = input()
        print("What is the password?")
        unencryptedPassword = input()
        unencryptedPassword = passwordEncrypt(unencryptedPassword, encryptionKey)
        newList = [website, unencryptedPassword]
        passwords.append(newList)
        print("Your password has been saved.")

    elif choice == "4":  # Save the passwords to a file
        savePasswordFile(passwords, passwordFileName)

    elif choice == "5":  # print out the password list
        for keyvalue in passwords:
            print(", ".join(keyvalue))

    elif choice == "6":  # quit our program
        sys.exit()

    print()
    print()
    ####### YOUR CODE HERE ######
    # You will need to find the password that matches the website
    # You will then need to decrypt the password
    #
    # 1. Create a loop that goes through each item in the password list
    #  You can consult the reading on lists in Week 5 for ways to loop through a list
    #
    # 2. Check if the name is found.  To index a list of lists you use 2 square backet sets
    #   So passwords[0][1] would mean for the first item in the list get it's 2nd item (remember, lists start at 0)
    #   So this would be 'XqffoZeo' in the password list given what is predefined at the top of the page.
    #   If you created a loop using the syntax described in step 1, then i is your 'iterator' in the list so you
    #   will want to use i in your first set of brackets.
    #
    # 3. If the name is found then decrypt it.  Decrypting is that exact reverse operation from encrypting.  Take a look at the
    # caesar cypher lecture as a reference.  You do not need to write your own decryption function, you can reuse passwordEncrypt
    #
    #  Write the above one step at a time.  By this I mean, write step 1...  but in your loop print out every item in the list
    #  for testing purposes.  Then write step 2, and print out the password but not decrypted.  Then write step 3.  This way
    #  you can test easily along the way.
    #

【问题讨论】:

  • 你听说过字典吗?
  • 我听说过,是的,但从未使用过。目前正在阅读它们。
  • 只是想知道。它们在这里很有用,但不是必需的。

标签: python python-3.x loops iteration string-length


【解决方案1】:

您似乎只想打印does not compute,前提是没有存储的密码与输入匹配;但实际上,您正在为每个不匹配的密码打印该消息(即使其他密码匹配)。

我已修改您的循环以在找到匹配项时中断,并且仅在未找到匹配项时打印消息(通过在 for 循环中添加 else 子句,该循环仅在循环使其全部完成时才执行一路走到尽头。)

    passwordToLookup = input()
    for i in range(len(passwords)):
        if passwordToLookup == passwords[i][0]:
            webSite = passwordEncrypt(passwords[i][1],-(encryptionKey))
            print()
            print('The password is ' + webSite+'.')
            print(i)
            print(passwords[i])
            print(passwords[i][0])
            break
    else:
        # if we got to the end of the loop, no passwords matched
        print('Does not compute!')

【讨论】:

    【解决方案2】:

    首先,我冒昧地重新格式化并改进了您的代码,使其看起来更漂亮。

    • 提示的多行字符串
    • 用于打印变量的 F 字符串(Python 3.4 及更高版本)
    • 使用新的black 模块进行格式化

    你的问题是你遍历所有存储的网站

        for i in range(len(passwords)):
            if passwordToLookup == passwords[i][0]:
                ...
            else:
                ...
    

    其实你应该做的是

    1. 检查网站是否存在于当前列表中
    2. 如果找到则返回解密密码,否则返回Cannot computer

    做 1. 的最佳方法是:

    • 将密码元组转换为字典:passwords = {"yahoo":"XqffoZeo", "google":"CoIushujSetu"}
    • 检查网站是否是键之一:if website in passwords.keys(): ...
    • 相应地更新其余代码(因为密码列表不是元组列表而是字典)

    或者更简单:在提取密码时,只需将元组列表转换为字典即可:

    elif choice == "2":  # Lookup at password
        print("Which website do you want to lookup the password for?")
        for keyvalue in passwords:
            print(keyvalue[0])
        print("----")
        passwordToLookup = input()
        dict_passwords = dict(passwords)
        if passwordToLookup in dict_passwords:
            encrypted = dict_passwords[passwordToLookup]
            password = passwordEncrypt(encrypted, -(encryptionKey))
            print(f"=> The password is {password}.")
        else:
            print("=> Does not compute!")
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2020-01-06
      • 2023-03-16
      • 1970-01-01
      • 2023-03-03
      • 2012-08-26
      • 2023-01-08
      • 1970-01-01
      • 2012-09-20
      相关资源
      最近更新 更多