Python Forum
Dictionary lookups exercise (PyBite #109)
Thread Rating:
  • 3 Vote(s) - 2.67 Average
  • 1
  • 2
  • 3
  • 4
  • 5
Dictionary lookups exercise (PyBite #109)
#11
Testing, testing. testing. That is what one needs to do when writing code. So I strongly advise to temporarily add a line to your code so you can see the result. Not needed to run the full assertion test every time, too much output. It will confuse you. Add this line so you can run your code:
print(get_workout_motd("monday"))
Output:
Not a valid day
(??? We expected: "Go train Chest+biceps". Well that is for you to find out. Smile )


Second:
if x in ('Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday'):
??? Surely you mean:
if cap_day in ('Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday'):
Third:
TRAIN = 'Go train {}'
Because of the curly braces I guess you wanted to do something with str.format(). Like this:
>>> TRAIN = 'Go train {}'
>>> print(TRAIN.format("Biceps"))
Go train Biceps
But why make it so difficult? You can also do:
>>> TRAIN = 'Go train '   #mind the extra space at the end
>>> print(TRAIN + "Biceps")
Go train Biceps
It is your choice.

Fourth:
x = WORKOUT_SCHEDULE.get(cap_day)
Well found, I did not even know it was possible. But for me the nice thing about dictionaries is that you can get the values by index (between square brackets). Like this:
x = WORKOUT_SCHEDULE[cap_day]
This should be the preferred method to retrieve values from a dictionary.

Fifth:
return (TRAIN, 'Go train {}')
No, that is not the way. Now you return two values. A tuple. But the assignment says you must return a string. One string. You can do that like this:
return TRAIN + x
Reply
#12
(Jul-17-2020, 03:24 PM)ibreeden Wrote: Testing, testing. testing. That is what one needs to do when writing code. So I strongly advise to temporarily add a line to your code so you can see the result. Not needed to run the full assertion test every time, too much output.

If there are unit tests, they should be run. That's the point of them! If there's too much output, there's something wrong. You should see if the tests have passed, or in the case of the failure, why the assertion failed, etc.
Reply
#13
Programming is not only thinking about how to write code, but also about how to solve the problem. The initial problem statement says that on weekdays you should return 'Go Train whatever' where 'whatever" is the dictionary value for the day, and that on the weekend you should return "Chill Out!'. The problem statement also says you dictionary value for weekends is 'Rest'. Finally the problem statement says if the input is not a day of the week you should return 'Not a valid day'

My initial pseudo code for this problem would be:
function motd(day)
    if day in dictionary
        if dictionary[day] = 'Rest'
            return chill out
        else
            return 'Go Train '+dictionary[day]
    return 'Not a valid day'
Converting to Python is pretty straightforward. The dictionary lookup is straight forward. Comparing the dictionary value to 'Rest" is straightforward. The trickiest part is identifying an invalid day. This is a really common problem that has to be solved in Python, and a quick search reveals there are two common approaches; using get, or wrapping the lookup in try/except. This is how the solution looks using try/except
INVALID_DAY = '{} is not a valid day'
CHILL_OUT = 'Chill out!'
TRAIN = 'Go train {}'
REST = 'Rest'
WORKOUT_SCHEDULE = {
    'Friday': 'Shoulders',
    'Monday': 'Chest+biceps',
    'Saturday': REST,
    'Sunday': REST,
    'Thursday': 'Legs',
    'Tuesday': 'Back+triceps',
    'Wednesday': 'Core'
    }
 
def get_workout_motd(day):
    try:
        x = WORKOUT_SCHEDULE[day.capitalize()]
        if x == REST:
            return CHILL_OUT
        return TRAIN.format(x)
    except KeyError as err:
        return INVALID_DAY.format(err)

while 1:
    print(get_workout_motd(input()))
And this is how it looks using get():
def get_workout_motd(day):
    x = WORKOUT_SCHEDULE.get(day.capitalize())
    if x is None:
        return INVALID_DAY
    if x == REST:
        return CHILL_OUT
    return TRAIN.format(x)
There are many ways this problem can be solved, and a big part of programming is finding a solution that is clear, robust and efficient. Making a set of weekday keys and a set of weekend keys and determining what set contained the entered day is not clear, robust or efficient. It is the kind of solution you only come up with when you are thinking about how to write code when you haven't fully thought out how to solve the problem. You are not good enough to do your design work at the keyboard, no programmers are.
Reply
#14
Hello Pythonistas: I’m back!

Thank you for all of your replies.

@ibreeden: Based on your suggestions, by passing different variables into the motd function, I was able to debug. Also, thank you for the tip to use str.format(). I didn’t realize that variables could be placed inside a string dynamically when using {}. Now I know. I incorporated this into my script (first function below).

@ndc85430: Yes, leveraging the unit tests provided by the instructor is important. To test the latest iteration of my script I’m now using both print and the unit tests.

Here was the next iteration of my motd() function which passed the unit test:

def get_workout_motd(day):
   cap_day = day.capitalize()
   # x = WORKOUT_SCHEDULE.get(cap_day)
   if cap_day in ('Monday',):
       return TRAIN.format(WORKOUT_SCHEDULE['Monday'])
   if cap_day in ('Tuesday',):
       return TRAIN.format(WORKOUT_SCHEDULE['Tuesday'])
   if cap_day in ('Wednesday',):
       return TRAIN.format(WORKOUT_SCHEDULE['Wednesday'])
   if cap_day in ('Thursday',):
       return TRAIN.format(WORKOUT_SCHEDULE['Thursday'])
   if cap_day in ('Friday',):
       return TRAIN.format(WORKOUT_SCHEDULE['Friday'])
   if cap_day in ('Saturday','Sunday'):
       return CHILL_OUT
   else:
       return INVALID_DAY
Hooray! I did it! This produces the correct output but it isn’t very elegant or efficient. It’s ultra naive as well. I explored some of the solutions provided by other PyBite contributors and adapted one of them to improve my script. Here is an alternate solution that I came up with:

def get_workout_motd(day):
   cap_day = day.capitalize()
   if cap_day in WORKOUT_SCHEDULE:
       if cap_day in ('Saturday','Sunday'):
           return CHILL_OUT
       else:
           return TRAIN.format(WORKOUT_SCHEDULE[cap_day])
   else:
       return INVALID_DAY
This one is more Pythonic, right? Much better.

@deanhystad: Thank you for your feedback. Sharing the pseudo code is instructive and helpful. But writing the solution to my homework assignment before I came up with a working solution myself is inappropriate for this subforum. You almost ruined the whole purpose of me learning to do it on my own. You should have shared the pseudo code but waited until after I produced my own working solution before sharing your’s. I have other homework assignments that I am working on next. Dear @deanhystad: For future reference, please wait until after I’ve completed my assignments before sharing best practices.
Reply
#15
Hi folks,

Sorry for reviving this post - it was very interesting to read the answers etc. but i am actually very keen to know what way of formatting the strings would you recommend to stick with?
I use f-strings (new to python & thanks to my book) but you in this thread actually use the below e.g:
TRAIN = 'Go train {}'
in connection with
return TRAIN.format(x)
Is it perfectly valid in python3 - i mean is it just something that dates back to python2 or it will be still around along the python3 therefore worth of picking it up as another way of formatting strings?

Btw, the below is my code (no string capitalisation as i actually have had all days in lower case hence lower() in code.)

def get_workout_motd(day):
    """Return a value for the given day or warning message."""

    day = day.lower()
    week_schedule = {'monday': 'chest & biceps', 'tuesday': 'back & shoulders',
                    'wednesday': 'neck & thighs', 'thursday': 'legs',
                    'friday': 'belly', 'saturday': 'rest', 'sunday': 'rest'}
    if day in week_schedule:
        if week_schedule[day] == 'rest':
            return 'Chill out!'
        else:
            return f'The day is {day.title()}, go train {week_schedule[day]}.'
    else:
        return 'Not a valid day!'

# run it :)

day = input("What day is it?: ")
print(get_workout_motd(day))
The code obviously does not strictly adhere to the requirements it is just my take at solving it..
Reply


Possibly Related Threads…
Thread Author Replies Views Last Post
  Type conversion and exception handling (PyBite #110) Drone4four 5 33,018 Jul-27-2020, 11:33 AM
Last Post: DeaD_EyE
  Iterating over dictionaries with the namedtuple function (PyBite #108) Drone4four 7 4,766 Jul-15-2020, 04:23 AM
Last Post: ndc85430
  Dictionary based exercise garvind25 2 1,958 Jul-12-2020, 06:53 PM
Last Post: garvind25
  "Slicing and dicing strings" - - PyBite #105 Drone4four 8 4,330 Jun-11-2020, 09:28 PM
Last Post: knackwurstbagel

Forum Jump:

User Panel Messages

Announcements
Announcement #1 8/1/2020
Announcement #2 8/2/2020
Announcement #3 8/6/2020