python 3 list homework has me stumped - list

okay, so I'm supposed to create a wizard inventory program that lists the items the wizard currently has on him. At most, he can hold 4 items, and starts with 3. My functions seem to be the issue, but I'm not sure what I'm doing wrong from the book.
My show function works like a charm...my edit isn't editing...and yeah. I'll just post this up, and hopefully you guys can clue me in on what I'm doing wrong. Thanks for all the help in advance. (No, I'm not asking anyone to do my homework...but maybe just point me in the right direction)
print ("The Wizard Inventory program")
inventory = ["orb", "staff", "spellbook"]
def opening_menu():
print("Command Menu")
print("show - Show all items")
print("grab - Grab an item")
print("edit - Edit an item")
print("drop - Drop an item")
print("exit - Exit program")
print()
def show_it():
inventory = ["orb", "staff", "spellbook"]
for item in inventory:
print(item)
def grab_it():
print("which item would you like to add??" )
if (item -1) in range (master_inventory_list):
while yes:
grab_it (inventory, " ")
def edit_it():
inventory = ["orb", "staff", "spellbook", "hat", "potion", "robe"]
item = input("What item are you looking for? ")
if item in inventory:
inventory.remove(item)
def drop_it():
inventory = ["orb", "staff", "spellbook", "hat", "potion", "robe"]
item = input("What item would you like to drop? ")
for item in inventory:
inventory.pop()
def exit_it():
choice = y
while choice.lower() == "y":
print("Do you want to stay inside your inventory? (y/n): ")
print()
print("Goodbye!!")
def master_inventory_list():
master_inventory_list = ["orb", "staff", "spellbook", "hat", "potion", "robe"]
opening_menu()
while True:
command = input("Command: ")
if command.lower() == "show":
show_it()
elif command.lower() == "grab":
grab_it()
elif command.lower() == "edit":
edit_it()
elif command.lower() == "drop":
drop_it()
elif command.lower() == "exit":
break
else:
print("Not a valid choice! Please choose again. \n")
print("Goodbye!")
if __name__ == "__main__":
main()

You said homework, so I'll assume you've just started learning in the past month or so.
Just taking a glance at it, perhaps it's the lack of return statements / global inventories / whatever reflects your changes in inventory?
def edit_it():
inventory = ["orb", "staff", "spellbook", "hat", "potion", "robe"]
item = input("What item are you looking for? ")
if item in inventory:
inventory.remove(item)
In a function (like edit_it), all your variables are either arguments to the function, created within the function, or global variables. If you want your inventory to reflect your changes, you need to output it in a return statement. A return statement will give you your list / inventory, but it's up to you to take the list. You can assign the value of the returned list to another variable.
However, because you define inventory inside the function, every time you call the function, you will do this declaration / assignment:
inventory = ["orb", "staff", "spellbook", "hat", "potion", "robe"]
Effectively, you would never get past 5 items. So in addition to a return function, you probably want to pass the inventory to your edit_it function as an argument every time you want to, well, edit it. So as an example:
def example(inventory, itemToRemove):
inventory.remove(itemToRemove)
return inventory
newThing = example(oldThing, theUserInput)
newerThing = example(newThing, theNewUserInput)
(These are terrible function names, by the way, but I think it gives a decent summary of the general structure I'm getting at. There's stuff to be said about efficiency and clarity, but meh.)
Additionally, if you don't mind me asking, why do you have master_inventory_list() as it is? If it's meant to be a value that you can use throughout your program, there's a better way (and it's not really how functions are to be used).

Related

Django - why does a list passed as context not clear on refresh, and instead duplicates?

Hard to explain this in a simple subject. This is with a GET, no POSTs.
I have a function defined in a different file, we'll say list_gen.py that returns list 'gen_list'. 'gen_list' is a global variable here.
In the views.py, I call this function and assign the output as 'output_list' and send it with the return as such: " return render(request, 'detail.html', {'output_list':output_list}.
Then, in detail.html I simply place the results with {{output_list}}.
When I visit the page, I see the exact output I expected. But, if press refresh, the output duplicates and continues to do so each time I press refresh or if I visit another entry that uses that detail.html page.
Has anyone seen this before?
Below is the view in question. The suspect list is "ped"
#login_required(login_url='/accessdenied/')
def detail(request, did):
try:
dog = Dogs.objects.get(did__exact=did)
resp = pedigree(did, 3)
ped = ''.join(map(str, resp))
try:
dam = Dogs.objects.get(did__exact=dog.dam).registered_name
except:
dam = "Not Listed"
try:
sire = Dogs.objects.get(did__exact=dog.sire).registered_name
except:
sire = "Not Listed"
parents = {'dam': dam, 'sire': sire}
except Dogs.DoesNotExist:
raise Http404("Dog does not exist")
return render(request, 'main/detail.html', {'dog': dog, 'parents': parents, 'ped': ped})
Below am image of the first time visiting the details for a specific entry (a dog):
And refresh a few times, and then visit a different entry. Note that each recent entry appears at the bottom.
The pedigree function (which calls printTree). Yes... I am making an html file into a list which is probably dumb. BUT, I get the exact same duplication if I use the "dog" list you see commented out where used.
dog = []
ped = ['<table border=1>']
def pedigree(did, max):
'''
:param did: id of the child dog
:param max: max number of generations to display
:return: list of dogs
'''
con = sqlite3.connect(f)
con.row_factory
cursor = con.execute('SELECT "Registered Name", ROUND(((JulianDay("now") - JulianDay("Date of Birth"))/365.25),1), "Sex" FROM dogs where did IS %s ' % did).fetchall()
for row in cursor:
name, age, gender = row[0], row[1], row[2]
sql = "SELECT a.Sire, a.Dam, s.'Registered Name', d.'Registered Name' FROM dogs a INNER JOIN dogs s ON a.Sire = s.did INNER JOIN dogs d ON a.Dam = d.did WHERE a.did = "
printTree(sql, did, name, 0, max)
return ped
#return dog
def printTree(stmt, did, name, N, max):
'''
:param stmt: sql statement to query information
:param did: dog to obtain information on
'''
rspan = 2**(max-N)
if (rspan > 1):
ped.append('<td rowspan='+str(rspan)+'><a href=/dogs/'+str(did)+'>'+name+'</td>')
# dog.append({'name': name, 'rspan': rspan})
else:
ped.append('<td><a href=/dogs/'+str(did)+'>'+name+"</td>")
if (N == max):
ped.append("</tr><tr>")
if(N < max):
s = None
d = None
sn = None
dn = None
con = sqlite3.connect(f).execute(stmt+str(did)).fetchall()
for row in con:
s, d, sn, dn = row[0], row[1], row[2], row[3]
if (s and sn) != None:
printTree(stmt, s, sn, N+1, max)
if (d and dn) != None:
printTree(stmt, d, dn, N+1, max)
Thanks to the comments, I fixed by altering the pedigree function as such to clear the list.
ped = []
def pedigree(did, max):
'''
:param did: id of the child dog
:param max: max number of generations to display
:return: list of dogs
'''
ped.clear()
ped.append('<table border=1>')
con = sqlite3.connect(f)

python3: how do i ask a user for input to select a specific list, (yes or no) and then print the items in that specific list in a random order?

python3: how do i ask a user for input to select a specific list, and then print the items in that specific list in a random order? and then repeat the program to ask the user if which list they would like to select
#lists of healthy food
Fruits = ['apples', 'oranges', 'pears']
Vegies = ['carrots', 'tomatoes', 'broccoli']
#lists of meats
Red_meat = ['steak', 'hamburgers']
White_meat = ['chicken', 'turkey']
import random
the code i have below just looks repetitive and annoying. there must be an easier way to print this as a string of text
****i would like to have the user asked for input (which list would you like
to select from?****
#Healthy foods #
#then print out something along the lines of
OUTPUT: oranges, tomatoes, pears, carrots
print(random.choice(Fruits), end= " ")
print(random.choice(Vegies), end= " ")
print(random.choice(Fruits), end= " ")
print(random.choice(Vegies), end= " ")
then ask the user if it would like to run the same list again, or select a
different list
#would you like to run this same list(yes or no)
if yes: (runs again)
if no: (Which list would you like to run?)
lists of meats:
print(random.choice(Red_meat), end= " ")
print(random.choice(White_meat), end= " ")
print(random.choice(Red_meat), end= " ")
print(random.choice(White_meat), end= " ")
OUTPUT: steak, turkey, hamburgers, chicken
again?
OUTPUT: hamburgers, chicken, steak, chicken
This does very non-bulletproof user input. It's suitable for a demo program but not for the real world.
To have a single print call you need to build up a list of the data you want the user to see. I've given you a sample but there are lots of ways to do it.
The loop in display_list may look a bit daunting but it is like that to make it easy to add new categories to Healthy_food and Meats. Your code has the fact that there are only 2 categories of each hard-coded into it.
import random
Healthy_food = dict(
#lists of healthy food
Fruits = ['apples', 'oranges', 'pears'],
Vegies = ['carrots', 'tomatoes', 'broccoli'],
)
Meats = dict(
Red_meat = ['steak', 'hamburgers'],
White_meat = ['chicken', 'turkey'],
)
All_food = {
1: Meats,
0: Healthy_food,
}
def display_list(choice): # choice can be 0: Healthy_food or 1: Meats
selection = []
for i in range(2): # gives 2 random choices from each category
for options in All_food[choice].values():
selection.append(random.choice(options))
print (' '.join(selection))
def interact():
response = input('Do you want a list of Meats or Healthy food, or Quit? ').lower()
while 'q' not in response and response != '':
while True:
display_list('meat' in response)
if 'y' not in input('Again? ').lower():
break
response = input('Do you want a list of Meats or Healthy food, or Quit? ').lower()
if __name__ == "__main__":
interact()

ValueError: list.remove(x): x not in list issue with Python

I have been working on a python problem for the past four days and I keep getting a small problem when I run my code. The error that I am getting is the following:
Traceback (most recent call last):
File "cuddy_m_chap10_7.py", line 163, in
main()
File "cuddy_m_chap10_7.py", line 121, in main
cr1.clear(r3)
File "cuddy_m_chap10_7.py", line 48, in clear
self.__list_item.remove(r)
ValueError: list.remove(x): x not in list
Now, I have researched this problem but cannot find anything that helps me. To start, I have a simple program that has three objects, which represent clothes. I have a cash register class and here are some of its methods:
def __init__(self):
self.__list_item = []
def purchase_item(self, r):
self.__list_item.append(r)
def clear(self, r):
for item in self.__list_item:
self.__list_item.remove(r)
As the program runs, the user may add clothes to a shopping cart or take clothes out. Now, if I add two pieces of clothing, I can use the clear method and take out a piece. However, if I have three pieces of clothing in the cart then get the trace back error. So, 2 items in cart, everything works fine, three or more pieces I get my error. Here is the code is some of the main function code:
#Creating the objects from the class
r1 = RetailItem('Jacket', 12, 59.95)
r2 = RetailItem('Designer Jeans', 40, 34.95)
r3 = RetailItem('Shirt', 20, 24.95)
#creating cash register object
cr1 = CashRegister()
print("Listing All Items:")
print('ITEM', '\t', '\t', '\t', 'PRICE')
print(r1.get_desc(), '\t', '\t', '\t', r1.get_price())
print(r2.get_desc(), '\t', '\t', r2.get_price())
print(r3.get_desc(), '\t', '\t', '\t', r3.get_price())
#Asking the user which items they want to buy
ch = 'y'
while ch.upper() == 'Y':
print()
print("Please enter the name of the item to be purchased")
item = input('Name: ')
if item.upper() == r1.get_desc().upper():
cr1.purchase_item(r1)
elif item.upper() == r2.get_desc().upper():
cr1.purchase_item(r2)
elif item.upper() == r3.get_desc().upper():
cr1.purchase_item(r3)
ch = input('Select another item: (y/n): ')
#Displaying a list of the items which have been placed in the cart
print()
print("The list of the items you have in your cart are as follows: ")
print(cr1.show_items())
print()
remove = input("Do you want to remove an item? (y/n) ")
while remove.lower() == 'y':
if remove.lower() == 'y':
print("Please enter the name of the item you want to be remove: ")
name = input('Item: ')
if name.upper() == r1.get_desc().upper():
cr1.clear(r1)
print("The", r1.get_desc(), "has been removed!")
elif name.upper() == r2.get_desc().upper():
cr1.clear(r2)
print("The", r2.get_desc(), "has been removed!")
elif name.upper() == r3.get_desc().upper():
cr1.clear(r3)
print("The", r3.get_desc(), "has been removed!")
remove = input("Do you want to remove an item? (y/n) ")
any help on why my program works with 2 items in the cart but not 3 will be greatly appreciated! Thank you
You should not be using a for loop at all. Just remove that one item:
def clear(self, r):
self.__list_item.remove(r)
You are trying to remove r from the list as many times as you have total items in the list..

Python cannot iterate a list completely

So I posted this before but I didn't follow the community guidelines so I decided to post it again this time following the community guidelines. (I tried to delete my other question but it wouldn't let me)
Here is the minimal amount of code I could do to create the same problem:
class Object:
def __init__(self, *args, **kwargs):
for k, v in kwargs.iteritems():
setattr(self, k, v)
self.inventory = []
try: self.itemComponent.owner = self
except: self.itemComponent = None
class Item:
def drop(self):
for obj in objects:
if self.owner in obj.inventory:
objects.append(self.owner)
obj.inventory.remove(self.owner)
def monster_death(monster):
monster.name = 'Goblin Corpse'
for element in monster.inventory:
if element.itemComponent:
element.itemComponent.drop()
objects = []
#Create Goblin
monster = Object(name = 'Goblin')
#Populate Goblin's Equipment
monster.inventory = [
Object(name='Dagger', itemComponent=Item() ),
Object(name='Light Healing Potion', itemComponent=Item() ),
Object(name='Scroll of Chain Lightning', itemComponent=Item())
]
objects.append(monster)
print '=~In Monster Inventory~='
for item in monster.inventory:
print item.name
print
print '=~In World~='
for obj in objects:
print obj.name
print
print '***MONSTER DIES***'
print
monster_death(monster)
print '=~In Monster Inventory~='
print
for item in monster.inventory:
print item.name
print
print '=~In World~='
print
for obj in objects:
print obj.name
What happens is one of the items always stays in the monsters inventory...it seems almost random which item stays in but it is always the same item every time unless I remove or add more items to his inventory.
You're removing from the list that you are currently iterating through, that will affect the iteration.
If you need to process each item, then do that in the loop, and then clear the list afterwards
my_list = ['a', 'b', 'c']
my_list[:] = [] # clear the list without replacing it

Issue with an exception from a class, how to get it to return the main-script?

I'm having an issue with an exception in my class. I want it to return to my main-script if that's even possible, or any solution which will avoid any crashing of my program. I'll show you the code.
Here's the main script:
from requestnew import requestNew
def chooseCountry():
countryc = input("Enter which country your city is in(in english): ")
rq.countrychoice.append(countryc)
def chooseCity():
cityc = cityc = input("Enter the name of the city: ")
rq.citychoice.append(cityc)
def makeForecast():
try:
for day in rq.data['forecast']['simpleforecast']['forecastday']:
print ("Country: ", rq.countrychoice[-1], "City: ", rq.citychoice[-1])
print (day['date']['weekday'] + ":")
print ("Conditions: ", day['conditions'])
print ("High: ", day['high']['celsius'] + "C", '\n' "Low: ", day['low']['celsius'] + "C", '\n')
except Exception as e:
print ("\nHave you typed in the correct country and city?\nBecause we got a" ,'"',e,'"', "error\nplease try again!")
return menu
if __name__ == '__main__':
"""Introducion"""
print ("\nThis program lets you see a weather forecast for your choosen city.")
rq = requestNew()
while True:
try:
print("\nWhen you have typed in country and city, press 3 in the menu to see the weather forecast for your choice.\n")
menu = int(input("\nPress 1 for country\nPress 2 for city\nPress 3 to see forecast\nPress 4 to exit\n"))
if menu == 1:
chooseCountry()
elif menu == 2:
chooseCity()
elif menu == 3:
rq.forecastRequest()
makeForecast()
elif menu == 4:
print ("\nThank you for using my application, farewell!")
break
elif menu >= 5:
print ("\nYou pressed the wrong number, please try again!")
except ValueError as e:
print ("\nOps! We got a ValueError, info:", e, "\nplease try again!")
continue
And here is my class code:
import requests
import json
class requestNew:
def __init__(self):
self.countrychoice = []
self.citychoice = []
def countryChoice(self):
self.countrychoice = []
def cityChoice(self):
self.citychoice = []
def forecastRequest(self):
try:
r = requests.get("http://api.wunderground.com/api/0def10027afaebb7/forecast/q/" + self.countrychoice[-1] + "/" + self.citychoice[-1] + ".json")
self.data = r.json()
except #?
As you can see above I use an exception in the def forecastRequest(self):. The problem is I don't know which exception and how to return it correctly to avoid any program crashes.
If you look at my main-script you can see that I have while True: to loop everything from the menu.
Everything in the program works correctly except if I press 3; elif menu == 3: without choosen both country from def chooseCountry(): or city from def chooseCity():.
This is because I'm using a list in my class and then print it in the def forecastRequest(self): like this; countrychoice[-1] to get the last appended list-item from input. And when I press 3 in the menu without choosing country or city, the list will be empty.
My question is, is there any way to let the except #? in def forecastRequest(self): to return the user to the menu in my main-script? Or is there any other way to avoid the program of crashing if the list is empty when I try to make the request?
Sorry for my english, and sorry if my explaining is messy, I've tried my best for it to be relatively easy to understand as possible.
If you want control to return to the main loop, catch the exception in the main loop:
elif menu == 3:
try:
rq.forecastRequest()
except IndexError:
# self.countrychoice[-1] will raise an IndexError if self.countrychoice is empty
# handle error
else:
makeForecast()