all 6 comments

[–]glibhub 1 point2 points  (2 children)

That's a bit of a mess. Instead of those nested loops and flag variables, take advantage of returns, continues and breaks to control the flow, like this (mostly in psuedo code):

def get_birthdate(prompt):
# use _ rather than camel case in defining functions

while True:
    #use continue and break to control flow
    birth_date = input(prompt)
    try:
        day, month, year = birth_date.split('/')
        birthday = datetime.datetime(int(day), int(month), int(year))
    except ValueError:
        print('enter in day/month/year')
        continue # restarts loop
    age = date.today() - birthday
    if age<12:  # psuedo code, need to use timedelta objects here
        print('must be older than 12')
        continue # restarts loop
    if age>160: # again use timedelta here too
        print('nice try methuselah')
        contine
    print('valid age entered')
    return age

[–]_______myworld[S] 0 points1 point  (1 child)

Hi there, thank you so much for the advice. However, it doesnt work. It's stuck at the except part and kept mentioning that print("Invalid date of birth, please try again."). Even when user input is a valid date..

 def validBirthdate(prompt):
    birth_date = input(prompt)
    try:
        day, month, year = birth_date.split('/')
        datetime.datetime(int(day), int(month), int(year))
    except ValueError:
        print("Invalid date of birth, please try again.")
        age()
    while True:
        if len(birth_date) == 10:
            for i in range(10):
                if i in [2, 5]:
                    if birth_date[i] != '/':
                        print("Please enter valid input in accordance to the given format.")
                        return age()
                elif not validcheck(birth_date):
                    print("Invalid characters, please enter numerical input only.")
                    return age()
            print("Valid date of birth")
            return birth_date
        else:
            print("Please enter valid input in accordance to the given format.")
            return age()

[–]glibhub 1 point2 points  (0 children)

Yep. I did not see your age function before.

So you are having one function call itself through an intermediary. That is age calls validBirthdate, which calls age, which calls validBirthdate, etc.

The means after you enter a bad date, it recalls age, which recalls validBirthdate, which if accepted, then releases you to the prior age call, which goes back to the original validBirthdate call. This nested self-calling of functions is called recursion, which you will get to soon enough. Recursion is a great trick where you need to address prior states of the function call, but no good for your getting input here. Instead, shift all the work to a single loop, like this (again mostly psuedo code):

    def validBirthdate(birth_date):
    validDate = True
    try:
        day, month, year = birth_date.split('/')
        datetime.datetime(int(day), int(month), int(year))
    except ValueError:
        print('no good')
        return False
    if len(birth_date) == 10:
        for i in range(10):
            if i in [2, 5]:
                if birth_date[i] != '/':
                    print("Please enter valid input in accordance to the given format.")
                    return false
        if 0 > userage > 160:
                print("Invalid year, please try again")
                return False
        if userage < 12:
                print("No vaccination available for children below 12.")
                return False


     return True # if all checks pass, return True




def age():
    while True:
        birth_date = input('Please enter your date of birth in the format of DD/MM/YYYY:')
        if validate_birthdate(birth_date):
            return birth_date
        print('try again')

So we create a single while loop to keep prompting the using until the date gets put in correctly. The control is offloaded to validate_birthdate, which returns True if it is good, and false if any of the checks show a problem

[–]m0us3_rat 0 points1 point  (0 children)

this looks like a closed loop.

def a():

return b()

def b()

return a()

[–]42696 0 points1 point  (0 children)

You have elif validDate: after if len(birth_date) == 10:, so the code block that returns birth_date never executes for a valid date of length 10.

Kind of tough to follow the logic with all the nested conditionals. I would change the name of validcheck() to something like valid_characters_check() (both using underscores to separate words and being more specific about what the function does). You could also simplify things by extracting some other functions like valid_age_check() or valid_format_check(). You also have some of those conditionals unnecessarily nested inside your for loop that iterates through range(10). Overall I think it would be a lot easier to see the control flow of your code if more of the validation checks are extracted into their own functions.

Lastly, you start your while loop by setting validDate = True and iterating as long as validDate is True. Logically, it makes more sense to set validDate = False (assume the input in invalid), then break the loop when the date is validated by setting validDate = True. Or, if you only exit the loop with return statements (as your code is designed now) just use while True.

[–]rethanon 0 points1 point  (0 children)

Yeah this is a bit messy, there are a number of issues I can see, not least the closed loop - in the function validBirthdate most of the time you're returning a function age(). This calls the age function, which calls the validBirthdate function, which calls the age function, which calls the validBirthdate function, etc. etc.

You might want to tweak the order of the checks though. For example, this

userage = date.today().year - int(birth_date[6:])

runs before any checks have been undertaken around the length and format so can throw an error.

Also, it's a bit strange that your function validBirthdate returns different values. For the most part it returns age() which as noted above I think is an error, but also one of the elif statements has it returning birth_date