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 trial
Michael B
3,990 PointsShopping List Program - Removing Items From the List
Sorry for formatting - I'm lost using markdown - my blank lines between paragraph disappear.
I extended the basic Shopping List program to allow the user to remove items from the list of items already created. I did this by adding an inner loop to allow for more than 1 item to be removed, The user must then type "DONE" to exit the inner processing loop and move back into the "main" processing loop.
This all works fine but I get "None" printed to the command line when I exit the inner loop. I don't understand how I can prevent this from happening.
In the example below I add aplles and then later remove them which takes me through the inner loop for item removal, and None is displayed (second last line in example below) after I finish the inner loop processing.
At the prompt i.e. '>', type in the item to add to your list and press ENTER.
Type 'DONE' to exit.
Type 'SHOW' to see your list.
Type 'CLEAR' to delete your list.'
Type 'REMOVE' to delete your list.'
Type 'SAVE' to save you list to file.'
> aplles
> apples
> eggs
> remove
Which items do you want to remove?
Type 'DONE' to exit.
rmv > aplles
Item "aplles" removed for the list.
There are 2 items in your list:
apples
eggs
rmv > done
None
Add more items!
Idiosyncratic behaviour that I'm not understanding or is there something else going on here?
I've tried return value, no return for my def but doesn't seem to make a difference.
Code:
def process_data():
# create an empty list to hold our items
items = []
print(display_help())
while True:
# ask for things for the list
item = input('> ')
# quit when DONE is entered
if item.upper() == 'DONE':
# quit
break
elif item.upper() == 'HELP':
# re-display the help message if requested
print(display_help())
elif item.upper() == 'SHOW':
# show the current list of items
print(display_list(items))
elif item.upper() == 'CLEAR':
# clear the list
if display_warning(items):
# delete the items in the list
items = []
# show the current list of items
print(display_list(items))
elif item.upper() == 'REMOVE':
# remove items from the list
print(remove_items(items))
print('Add more items!')
else:
if item in items:
print('"{}" already in list'.format(item))
print('Add it again?')
response = input('> ')
if response.upper() == 'YES' or response.upper() == 'Y':
items.append(item)
else:
# add the item to the items list
items.append(item)
print(display_list(items))
def remove_items(items):
print('Which items do you want to remove?')
print("Type 'DONE' to exit.")
while True:
item = input('rmv > ')
if item.upper() == 'DONE':
break
elif item in items:
items.remove(item)
print('Item "{}" removed for the list.'.format(item))
print(display_list(items))
elif item not in items:
print('Item {} is not in the list.'.format(item))
def display_warning(items):
print('Are you sure you want to delete the list of items?')
# show the current list of items
print(display_list(items))
print('Type YES to delete the list.')
response = input('> ')
if response.upper() == 'YES' or response.upper() == 'Y':
return True
else:
return False
def display_list(items):
# tell the user how many items are in the list
if len(items) == 0:
string = 'There are no items in your list!'
elif len(items) == 1:
string = 'There is 1 item in your list:'
else:
string = 'There are {} items in your list:'.format(len(items))
for item in items:
# add a line feed and the the item
string += '\n' + str(item)
return string
def display_help():
string = """
At the prompt i.e. '>', type in the item to add to your list and press ENTER.
Type 'DONE' to exit.
Type 'SHOW' to see your list.
Type 'CLEAR' to delete your list.'
Type 'REMOVE' to delete your list.'
Type 'SAVE' to save you list to file.'
"""
return string
if __name__ == '__main__':
process_data()
Not a huge issue but obviously not understanding how to deal with this so an explanation would help.
Thanks in advance for you help!!
Michael B
3,990 PointsThe preview didn't provide a very good representation of the final product so what I thought was an issue with Markdown actually wasn't anything at all. But thanks for the tips on Markdown ... always good to know.
1 Answer
Gavin Ralston
28,770 Pointselif item.upper() == 'REMOVE':
# remove items from the list
print(remove_items(items))
print('Add more items!')
Think about what that print statement is doing there in the REMOVE choice:
It's printing the result of the action remove_items() which returns...nothing (None). Chances are you didn't mean to wrap that in a print function anyway. :)
Hope that helps!
Michael B
3,990 PointsYes, the code is a bit of a mess ... I was messing about with TDD and was trying to work out whether one could test something like:
def display_help():
print ("""
At the prompt i.e. '>', type in the item to add to your list and press ENTER.
Type 'DONE' to exit.
Type 'SHOW' to see your list.
Type 'CLEAR' to delete your list.'
Type 'REMOVE' to delete your list.'
Type 'SAVE' to save you list to file.'
""")
I couldn't see how one would include something like this in a suite of tests (lets not talk about "whether one should test" just yet) so I converted it to a def that returned a string:
def display_help():
string = """
At the prompt i.e. '>', type in the item to add to your list and press ENTER.
Type 'DONE' to exit.
Type 'SHOW' to see your list.
Type 'CLEAR' to delete your list.'
Type 'REMOVE' to delete your list.'
Type 'SAVE' to save you list to file.'
"""
return string
I could then print(display_help()) and also include it in my unit testing.
So:
elif item.upper() == 'REMOVE':
# remove items from the list
print(remove_items(items))
print('Add more items!')
is a remnant of that experimentation.
Now, should one aim to include unit tests for code like this? I originally thought no but there might be occasion to do so, although I cannot think of an example of same. Should I bother testing something like this?
Thanks again!
Gavin Ralston
28,770 PointsHere's my thought:
Should you test the display_help() function that returns nothing and prints a hard coded string using a built in method (print)?
I'd say no. You don't need to test if print works, because the folks who wrote print should be testing that. You're essentially wrapping your method call and string up so it's tidier, right? That's pretty straightforward and will make you hate testing.
Now if your display_help() took input (like a dict/hash of help categories and their descriptions) and returned output based on that input (like, going through the list of options and setting up the keywords your program will respond to as well as creating the menu) the answer should be yes.
Once you make a test for something like that, you can make implementation changes within display_help() and not worry that went and broke it unexpectedly--you'd be testing that things still work exactly as expected.
Gavin Ralston
28,770 PointsGavin Ralston
28,770 PointsHere's the only real tricky parts for markdown:
Leave a blank line between whatever you're typing and what you want to format, and don't forget to tell the forum what type of syntax you want to highlight.