Welcome to the Treehouse Community
Want to collaborate on code errors? Have bugs you need feedback on? Looking for an extra set of eyes on your latest project? Get support with fellow developers, designers, and programmers of all backgrounds and skill levels here with the Treehouse Community! While you're at it, check out some resources Treehouse students have shared here.
Looking to learn something new?
Treehouse offers a seven day free trial for new students. Get access to thousands of hours of content and join thousands of Treehouse students and alumni in the community today.
Start your free trialAlex Miel
2,592 PointsPython time_machine() challenge. Is there a better way?
The attached code works to pass the challenge, but it feels cobbled together.
I tried to find a way to pass the 'unit' variable directly through the timedelta function because the if/elif structure doesn't seem very DRY. But I can't find a way to convert the 'unit' string into a variable (ie: datetime.timedelta('minutes' = num) doesn't work).
Also, using the 'starter' variable in the return statement, even though it's outside the scope of the function, seems weird.
Like I said, it ran fine, but am I missing something? Thanks.
import datetime
starter = datetime.datetime(2015, 10, 21, 16, 29)
# Remember, you can't set "years" on a timedelta!
# Consider a year to be 365 days.
## Example
# time_machine(5, "minutes") => datetime(2015, 10, 21, 16, 34)
def time_machine(num, unit):
if unit == 'minutes':
future = datetime.timedelta(minutes = num)
elif unit == 'hours':
future = datetime.timedelta(hours = num)
elif unit == 'days':
future = datetime.timedelta(days = num)
elif unit == 'years':
future = datetime.timedelta(days = num*365)
return starter + future
3 Answers
William Li
Courses Plus Student 26,868 PointsI think your code is alright.
But since you are asking to DRY up code and the possibility of passing in unit directly to timedelta, does the following look better to you?
def time_machine(num, unit):
if unit in ("minutes", "hours", "days"):
keyword = {unit : num}
elif unit == "years":
keyword = {"days" : num * 365}
return starter + datetime.timedelta(**keyword)
Alex Miel
2,592 PointsThank you yes, that's exactly what I meant.
I guess I didn't realize unpacking a dictionary passes the key as a variable, rather than a string. For example, if I create the dictionary, future = {'minutes' : 5}, to pass as a variable, this doesn't work:
warp = datetime.timedelta(future)
While this does:
warp = datetime.timedelta(**future)
This behavior is... unexpected. I suppose I don't understand unpacking as well as I hope to yet, but I'm happy to know there's a way to do this. Thanks again.
Kenneth Love
Treehouse Guest Teacherfuture = {'minutes': 5}
warp = datetime.timedelta(**future)
warp = datetime.timedelta(minutes=5)
The two timedelta
lines are exactly the same to Python. The **
turns the dict into keyword arguments.
Alex Miel
2,592 PointsI see. It makes more sense if I think about unpacking a dictionary as passing keyword=value directly. I couldn't find any way to output the unpacking without reverting the results back into strings so it was hard to tell what it was doing, exactly. I see how this could be a very powerful feature.
Thanks!
John Alexander Davidson
5,368 PointsThanks for sharing. I'm trying to work out why your code passes the challenge and mine doesn't. We wrote quite similar pieces but I keep getting an '<variable> isn't referenced before assignment'. When I assign it I keep failing the challenge.
import datetime
starter = datetime.datetime(2015, 10, 21, 16, 29)
# Remember, you can't set "years" on a timedelta!
# Consider a year to be 365 days.
## Example
# time_machine(5, "minutes") => datetime(2015, 10, 21, 16, 34)
def time_machine(num, string):
if string.lower == 'years':
add = datetime.timedelta(days = 365*num)
elif string.lower == 'days':
add = datetime.timedelta(days = num)
elif string.lower == 'hours':
add = datetime.timedelta(hours = num)
elif string.lower == 'minutes':
add = datetime.timedelta(minutes = num)
return starter + add
Kenneth Love
Treehouse Guest TeacherBecause the method is .lower()
, not .lower
(which would be an attribute).
John Alexander Davidson
5,368 PointsThanks Kenneth...
.doh()
joleneoropilla
17,214 Pointsjoleneoropilla
17,214 PointsAlex, thanks for asking this question. I was in the same boat where I wanted to find a more streamlined alternative to this challenge instead of my current clunky solution (which looks like your code) .