4

I have a function that performs a monthly task on one or more specified days (e.g., the first and the 15th.) For enhanced usability, I want to let users just pass in a single int when they only want it to happen one day each month, or a list of ints for multiple events per month.

monthly_event(days_of_month=1, event="paycheck") 
monthly_event(days_of_month=[1,15], event="bills", starting=date(2013,1,1))

Internally the function will iterate over the list and do the same thing it would do for a single int.

Since "int" is not an iterable, I need to do something to avoid a TypeError when the user just passes a single int. I was surprised to find that using an "or" expression and relying on short-circuiting does not work - the TypeError still happens. Here's an example:

from datetime import date as date
dt = date.today()
days = 1
#days = [1,2]
if dt.day == days or dt.day in days:
    print "GOOD"
else:
    print "BAD"

My first question is: have I misunderstood Python, or does the internal typecheck really happen on the entire line of code before the short-circuiting of the boolean expression? That seems very strange.

My second question is: what is the Pythonic way to do this? I'd like to avoid doing an explicit type check on the "days" variable. Using a try/catch instead just bloats the code:

try:
    if dt.day == days:
        print "GOOD"
    else:
        print "BAD"
except TypeError:
    if dt.day in days:
        print "GOOD"
    else:
        print "BAD"

Is there something obvious I've overlooked?

3
  • 1
    days = days if hasattr(days, "__iter__") else [days] Commented Jun 23, 2012 at 22:06
  • or: import collections; days = days if isinstance(days, collections.Iterable) else [days] Commented Jun 23, 2012 at 22:25
  • Just require days_of_month to always be an iterable (as its name suggests!). If the caller only wants one day, they can pass in a one-tuple or a list or set with length one or whatever. Commented Apr 19, 2015 at 19:16

1 Answer 1

6

I believe the problem occurs when dt.day != days (and the short circuit is not taken), Python will then try the dt.day in days expression, and get a TypeError.

Sign up to request clarification or add additional context in comments.

1 Comment

Ugh - that's kind of embarrassing. Thanks.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.