简体   繁体   English

用户输入-验证和确认-

[英]User input - validation and confirmation -

I am trying to perform something that has certainly been asked several times before (specifically Asking the user for input until they give a valid response , but I'm either trying to do something too complex or not thinking about my loops the correct way. 我正在尝试执行某些之前肯定会被要求执行的操作(特别是要求用户提供输入信息,直到他们给出有效的响应为止 ,但是我正在尝试执行过于复杂的操作或没有以正确的方式考虑循环。

In the code below, I am trying to do a few things: 在下面的代码中,我正在尝试做一些事情:

  • Ask the user for a list of integers, could be one or several (in this case, loan_ids ) 向用户询问整数列表,可以是一个或多个(在这种情况下,是loan_ids
  • If the integer fails, reject the input loudly 如果整数失败,请大声拒绝输入
  • if an integer, append to a running list 如果是整数,则追加到运行列表
  • Convert all results to tuples to they can be used in a SQL query 将所有结果转换为元组,以便在SQL查询中使用它们

In the second func, I am trying to combine the first one and then also ask the user to confirm the loan_ids before cutting out: 在第二个func中,我尝试合并第一个func,然后还要求用户在loan_ids之前确认loan_ids

  • If the user enters y , then end the loop 如果用户输入y ,则结束循环
  • If the user enters n , go back to the first function and ask again 如果用户输入n ,请返回第一个功能并再次询问
  • If anything else is entered, ask the user to resubmit the answer 如果输入了其他内容,请要求用户重新提交答案

I'm trying not to violate the Don't Repeat Yourself principle, but for the life of me I can't figure out the placement of the loops. 我试图不违反“不要重复自己”的原则,但是对于我一生,我无法弄清楚循环的位置。 I'm also relatively new to python and programming structure, so open to idiomatic comments on the design as well 我对python和编程结构还比较陌生,因此也欢迎对设计发表惯用的评论

def get_unique_loans_from_user():
    """Get list of  loan_ids from user

    This function is mean to capture raw loan_ids a user wishes to look up. 

    Returns tuple of unique loan_ids

    """

    loan_ids = []
    while True:    
        loan_id = raw_input('> Loan Id: ')
        # If nothing entered, exit
        if len(loan_id)==0:
            break
        # Make sure an integer was entered      
        else:
            try:
                int(loan_id)
            except ValueError:
                print loan_id + " is not a real integer, so likely not a valid loan id"
                continue
        # if an integer was entered, append to running list as an integer and continue
        # We only need to return the unique list of loan ids
            else:
                loan_ids.append(int(loan_id))

    # Convert unique list of loans to tuple to use in SQL     
    loans = tuple(np.unique(loan_ids))   

    # Return the tuple of loans
    return loans

And the second piece - the way it's currently written forces the same result when a user enters anything but y - I'm trying to cause different behavior depending on whether the use has invalid input vs. actually confirms the loan_ids are incorrect. 第二部分-当前编写的方式会在用户输入除y任何其他内容时强制产生相同的结果-我试图根据用户使用的输入是否无效而实际导致的loan_ids错误,从而导致不同的行为。 I also have used an extra break statement at the end, which I'm fairly sure is not best practice 最后,我还使用了一个额外的break语句,我敢肯定这不是最佳实践

def confirm_loan_ids():
    """ Confirm the list of loan ids is what the user wanted"""

    while True:

        # Get loan ids from user through raw input
        ids = get_unique_loans_from_user()

        # Print out the ids to the user
        print "Printing loan ids. There are {0} ids".format(len(ids))
        print ids

        # Confirm with user these are the correct ids
        answer = raw_input('> Are these the loan ids you expected? [y/n] ')


    # If user confirms correct, and continue
        if answer == 'y':
            print "\nExcellent - moving on\n"
            print "Here are your loan ids:"
            print ids
            break
    # If the answer is n, repeat the question
        elif answer == 'n':
            print "\n-------------> Let\'s try again\n"
            continue
    # If answer is not no or yes, ask again    
        elif (len(answer) == 0) or (answer not in ('y','n')):
            print "Please enter only y or n"
            continue
        else:
            print "This is only a test"
        # The If loop only breaks when the answer is 'y'
        break

    return ids

Try this. 尝试这个。 It reduces some of the requirements to use continue , instead letting the loop naturally iterate again. 它减少了使用continue一些要求,而让循环自然地再次迭代。 This reduces visual noise in the code. 这样可以减少代码中的视觉噪声。

For your second function, you can again simplify the logic to remove the need to use continue, instead only breaking when the input is good. 对于第二个功能,您可以再次简化逻辑以消除使用继续的需要,而仅在输入良好时才中断。

The code needs to loop again for the yes/no confirmation, so to avoid issues with having to break out of nested loops, the yes/no loop is in another function. 代码需要再次循环以进行“是/否”确认,因此为避免必须退出嵌套循环的问题,“是/否”循环位于另一个函数中。 This function won't return until a valid input is received. 在收到有效输入之前,此函数不会返回。

Hopefully this gives you some slightly clearer logic to work with? 希望这使您可以使用一些更清晰的逻辑?

You can reinstate your numpy.unique function if you want instead of set , but I don't generally use numpy and importing it just for that purpose seems a bit excessive I used set instead. 如果需要而不是set ,可以恢复numpy.unique函数,但是我通常不使用numpy ,并且仅出于此目的导入它似乎有点过分,而我改用set I don't know your exact requirements, so don't know if set or numpy.unique is more appropriate. 我不知道您的确切要求,所以也不知道setnumpy.unique是否更合适。

from __future__ import print_function

def get_unique_loans_from_user():

    loan_ids = []

    while True:
        loan_id = raw_input('> Loan Id: ')

        try:
            loan_id_int = int(loan_id)

            if loan_id_int == 0:
                break

            loan_ids.append(loan_id_int)
        except ValueError:
            print("%s is not a real integer, so likely not a valid loan id" % loan_id)

    # note: this will alter the order.
    return tuple(set(loan_ids))


def yesnoconfirm(msg):

    while True:
        answer = raw_input(msg)

        if answer in ('y', 'n'):
            return answer
        else:
            print('not a valid input')


def confirm_loan_ids():

    while True:

        ids = get_unique_loans_from_user()

        print("Printing loan ids. There are {0} ids".format(len(ids)))
        print(ids)

        answer = yesnoconfirm('> Are these the loan ids you expected? [y/n] ')

        if answer == 'y':
            break
        elif answer == 'n':
            print("\n-------------> Let\'s try again\n")
        else:
            print("oops something went wrong")

    print("\nExcellent - moving on\n")
    print("Here are your loan ids:")
    print(ids)

    return ids

print(get_unique_loans_from_user())
raw_input('continue?')
confirm_loan_ids()

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM