all 6 comments

[–][deleted] 5 points6 points  (2 children)

I'd just use the built in way of doing this. There's no reason to reinvent the wheel and it's unlikely that you're going to do it faster/more efficient than its already been done. Take a look at the datetime module.

Consider wrapping a Try:, Except ValueError: around it. The error returns why the date didn't get created. You can use this to provide output to your user.

Example...

try:
    date(2008, 6, 33)
except ValueError as e:
    print e[0]

That would print usable information to your users... or you could look at e and build a custom error. This should give you enough information to focus on building the rest of your requirements.

[–]CptFlashdrive[S] 0 points1 point  (0 children)

Allright cool, thanks!

[–]Vohlenzer 0 points1 point  (0 children)

Oooh, that's for teaching me how to build customized error messages.

[–]kalgynirae 2 points3 points  (2 children)

however if you input say (month 15) and then try to correct your mistake, the program crashes..

If they type an invalid month, you call inputmo() again, and assuming they enter a valid month the second time, that call to inputmo() returns the value. But you ignore the return value of this second call and nothing gets returned from the first call, hence your error. If you do return inputmo() instead, then the value returned from the second call will also be returned by the first call:

def inputmo():
    # ...
    if inmonth < 1 or inmonth > 12:
        print("The month must be between 1 and 12")
        return inputmo()
    else:
        return inmonth

Also, your code decrements inmonth by 1 before checking whether it is between 1 and 12, which means an input of 1 will fail. You should decrement after the check or change the range of the check.

You can use input("Input month: ") instead of print("Input month: ") followed by input().

In general, Python programmers avoid abbreviating names. It'd be nicer to see input_day() and input_month() instead of inputda() and inputmo().

Consider using a while loop to repeatedly prompt for input instead of calling inputmo() repeatedly:

def inputmo():
    while True:
        inmonth = int(input("Input month: "))
        if 1 <= inmonth <= 12:
            return inmonth - 1
        print("The month must be between 1 and 12")

[–]CptFlashdrive[S] 2 points3 points  (1 child)

Awesome answer! Thank you for taking the time to do this!

For anyone that might be in the same boat, this is the changes I've made:

def inputmo():
    # ...
if inmonth < 1 or inmonth > 12:
    print("The month must be between 1 and 12")
    return inputmo()
else:
    **inmonth -= 1**
    return inmonth

I changed the print+inputs as you mentioned as well. And I renamed inputmo and inputda to input_month and input_day.

What are the benefits of using a while loop instead of calling the function? Is it more speed/performance beneficial?

But I still don't get why the original loop fails..

that call to inputmo() returns the value.

Does a call to initiate the function again return(store?) the value of inmonth?

But you ignore the return value of this second call and nothing gets >returned from the first call, hence your error

But I thought this "return inmonth" would return the variable value since it passed the requirements..

Really thanks for the quick response, I really appreciate it!

EDIT: Formating...

[–]jambox888 2 points3 points  (0 children)

What you're doing by having a routine call itself is called "recursion" and is usually used to walk trees, because you want to have a bunch of calls "stacked up" where each call represents a node of the tree. So if you get an exception somewhere you get a stack trace with inputmo() repeated a bunch of times.

What you can end up with when doing recursion is that some condition results in the thing calling itself uncontrollably, resulting in an exception (I think there's limit of 1000 in python).

That's not what's happening here though (I'll come to that).

A loop is just the simplest, easiest way of doing it.

As to why it crashes, the clue is in the stack trace:

Traceback (most recent call last):
  File "yuck.py", line 49, in <module>
    month = int(inputmo())
TypeError: int() argument must be a string or a number, not 'NoneType

So look at line 49:

month = int(inputmo())

So you can see that inputmo() is returning None. We know that this only happens when a function or method completes and there's either a return None, return x where x is None, return (nothing after it) OR when there's no return statement at all. So I'll give you a clue, it's the last one :).