开发者

Restart exception handling if one part fails

I have the following snippet:

def check1(n):
    if len(n) != 4:
        return raw_input("Enter 4 digits only")
    else:
        return True

de开发者_如何学编程f check2(n):
    if n.isdigit() != True:
        return raw_input("Enter digits only")
    else:
        return True

def check3(n):
    if len(set(str(n))) != 4:
        return raw_input("Enter non duplicate numbers only")
    else:
        return True

sturn = 1
lturn = 8       

a = raw_input("Enter the 4 numbers you want to play with: ")

for turn in range(sturn, lturn):
    b = raw_input("Enter your guess: ")
    if (check1(b) != True or check2(b) != True or check3(b) != True):
        if check1(b) != True:
            print check1(b)
        elif check2(b) != True:
            print check2(b)
        elif check3(b) != True:
            print check3(b)
    else:
        print b

How can I rewrite this such that if any of the check functions fail, it starts from the b = raw_input line again and retests all the checks.

UPDATE I've improved the code after heeding the advice from keithjgrant and m1k3y02 but it doesn't work properly. If I enter '1' consecutively, it bounces between different exceptions instead of staying on the first check.

def checks(n):
    if len(n) != 4 or n.isdigit() != True or len(set(str(n))) != 4:
        return False
    else:
        return True

sturn = 1
lturn = 8       

a = raw_input("Enter the 4 numbers you want to play with: ")

for turn in range(sturn, lturn):
    b = raw_input("Enter your guess: ")
    while checks(b) != True:
        if len(b) != 4:
            b = raw_input("Enter 4 digits only")
        if b.isdigit() != True:
            b = raw_input("Enter digits only")
        if len(set(str(b))) != 4:
            b = raw_input("Enter non duplicate numbers only") 

    print b


Your question, as it stands, has nothing to do with exceptions. Try the following:

checks = [
    lambda n: (len(n)==4, "Enter 4 digits only."),
    lambda n: (n.isdigit(), "Enter digits only."),
    lambda n: (len(set(str(n)))==4, "Enter non duplicate numbers only.")
]

a = raw_input("Enter the 4 numbers you want to play with: ")

sturn = 1
lturn = 8
for turn in range(sturn, lturn):
    b = raw_input("Enter your guess: ")
    all_good = True

    for check in checks:
        good,msg = check(b)
        if not good:
            print msg
            all_good = False
            break

    if all_good:
        print "{0} is correct!".format(b)
        break

You could rewrite it to use exceptions as follows:

class CheckError(Exception): pass

class WrongLengthError(CheckError): pass
def check1(n):
    if len(n) != 4:
        raise WrongLengthError("Enter 4 digits only.")

class NonDigitCharError(CheckError): pass
def check2(n):
    if not n.isdigit():
        raise NonDigitCharError("Enter digits only.")

class HasDuplicatesError(CheckError): pass
def check3(n):
    if len(set(str(n))) != 4:
        raise HasDuplicatesError("Enter non duplicate numbers only.")


a = raw_input("Enter the 4 numbers you want to play with: ")

sturn = 1
lturn = 8
for turn in range(sturn, lturn):
    b = raw_input("Enter your guess: ")

    try:
        for check in (check1, check2, check3):
            check(b)

        print "{0} is correct!".format(b)
        break
    except CheckError, c:
        print c


you should try to create wrapper function which will contain all the checks. Once one will fail call the function again and again


What do you mean by "starts from the first one again?" Do you mean go back to the raw_input? You could put it in a while and loop until you have a valid input.

I would also suggest combining your check functions into one. You also call each one twice, when you really don't need to; just capture the response as you go.

valid_response = False
while not valid_response:
    input = raw_input("Enter your guess: ")
    valid_response = checkInput(input)
    if not valid_response:
        print valid_response
    else:
        print input

Even that can be cleaned up further, but hopefully it will point you in the right direction. I feel icky using valid_response to handle a string or a boolean there; you can probably find a way to separate the two by rethinking how your check function works.


Update

You've got a couple problems: You're still performing your checks multiple times, and you're combining your verification logic with your raw_input() calls. Because you're checking both for validity of input (a boolean value) and a reason for invalid data (more options), it probably makes more sense to not use an external function. Especially since we're only talking about a couple lines of code. Try this:

sturn = 1
lturn = 8       

# you never do anything with this variable "a". Did you mean to type "b" here?
a = raw_input("Enter the 4 numbers you want to play with: ")

for turn in xrange(sturn, lturn):
    valid_input = False
    b = raw_input("Enter your guess: ")
    while not valid_input:
        if len(b) != 4:
            b = raw_input("Enter 4 digits only")
        elif b.isdigit() != True:
            b = raw_input("Enter digits only")
        elif len(set(str(b))) != 4:
            b = raw_input("Enter non duplicate numbers only") 
        else:
            valid_input = True                 # breaks you out of your while loop
            print b

The one thing I haven't really evaluated in this code is whether or not the three checks work, since I'm not quite sure what you're going for with them. If you haven't already, it might be worth testing each one individually to make sure they are actually validating the user input the way you need them to.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜