Search code examples
pythonpython-3.xvalidationsplitvalueerror

How do I make a validation loop to make sure the user inputs the correct amount of times in a .split input?


This may be kind of stupid but I've made a really roundabout way of validating a credit card number. I'm still really new at python and coding in general and wanted to make it so that I can validate the amount of digits, whether or not the input is numbers, and to also make it so I can print the input split up like this: xxx-xxxx-xxxx

So far I have this (please excuse how messy and probably unnecessary a lot of it is!)

CreditOne = 0
CreditTwo = 0
CreditThree = 0

while True:
    CreditOne, CreditTwo, CreditThree = input("Enter the credit card number (separate with spaces): ").split()
    CreditCardList = [CreditOne, CreditTwo, CreditThree]
    CreditCardNumber = "-".join(CreditCardList)
    if CreditOne.isdigit() and CreditTwo.isdigit() and CreditThree.isdigit() and len(CreditOne) == 4 and len(CreditTwo) == 4 and len(CreditThree) == 4:
        break
    elif CreditOne == 0 or CreditTwo == 0 or CreditThree == 0:
        print("Please input a valid credit card number.")
        continue
    else:
        print("Please input a valid credit card number.")
        continue

print(CreditCardNumber)

It does the job for the most part except for the fact that if the user just inputs something like 4 4 or like a singular letter it will get a ValueError:

ValueError: not enough values to unpack (expected 3, got 1)

Basically what I've been trying to do is create a validation that allows the loop to continue after the error and return to the start of the loop. I've tried a try except loop and it didn't work, I wanted to get a second opinion on this and maybe some help from somebody who understands what I'm trying to achieve with my code.


Solution

  • Instead of unpacking first, then combining them into a list, do it the other way around:

    CreditCardList = input("Enter the credit card number (separate with spaces): ").split()
    if len(CreditCardList) == 3:
        CreditOne, CreditTwo, CreditThree = CreditCardList
        # ... do other stuff
    else:
        print("You must enter exactly 3 numbers")
    

    As a side note, study generator expressions, list comprehensions and built-ins such as all and any to further simplify your code. For example, the following line:

    if CreditOne.isdigit() and CreditTwo.isdigit() and CreditThree.isdigit() and len(CreditOne) == 4 and len(CreditTwo) == 4 and len(CreditThree) == 4:
    

    can be rewritten as

    if all(c.isdigit() and len(c) == 4 for c in CreditCardList):