The position argument error and resolving it - python-3.x

I am trying to implement a shopping cart in python and have this code but the error is that when i am calling a print_menu function , the arguments are not correct.
class ItemToPurchase:
def __init__(self, item_name= 'none', item_price=0, item_quantity=0, item_description = 'none'):
self.item_name = item_name
self.item_price = item_price
self.item_quantity = item_quantity
self.item_description = item_description
def print_item_cost(self):
string = '{} {} # ${} = ${}'.format(self.item_name, self.item_quantity, self.item_price, (self.item_quantity* self.item_price))
cost = self.item_quantity * self.item_price
return string, cost
def print_item_description(self):
string = '{}: {}'.format(self.item_name, self.item_description)
print(string, end=' ')
return string
class ShoppingCart:
def __init__(self,customer_name= None ,current_date='January 1,2016',cart_items=[]):
self.customer_name = customer_name
self.current_date = current_date
self.cart_items = cart_items
def add_item(self):
print('\nADD ITEM TO CART', end='\n')
item_name = str(input('Enter the item name:'))
item_description = str(input('\nEnter the item description:'))
item_price = int(input('\nEnter the item price:'))
item_quantity = int(input('\nEnter the item quantity:\n'))
self.cart_items.append(ItemToPurchase(item_name, item_price, item_quantity, item_description))
def remove_item(self):
print()
print('REMOVE ITEM FROM CART', end='\n')
string = str(input('Enter name of item to remove:\n'))
i = 0
for item in self.cart_items:
if(item.item_name == string):
del self.cart_items[i]
i += 1
flag=True
break
else:
flag=False
if(flag==False):
print('Item not found in cart. Nothing removed.')
def modify_item(self):
print('\nCHANGE ITEM QUANTITY', end='\n')
name = str(input('Enter the item name:'))
for item in self.cart_items:
if(item.item_name == name):
quantity = int(input('Enter the new quantity:'))
item.item_quantity = quantity
flag=True
break
else:
flag=False
if(flag==False):
print('Item not found in cart. Nothing modified.')
def get_num_items_in_cart(self):
num_items = 0
for item in self.cart_items:
num_items += item.item_quantity
return num_items
def get_cost_of_cart(self):
total_cost = 0
cost = 0
for item in self.cart_items:
cost = (item.item_quantity * item.item_price)
total_cost += cost
return total_cost
def print_total(self):
total_cost = self.get_cost_of_cart()
if (total_cost == 0):
print('SHOPPING CART IS EMPTY')
else:
self.output_cart()
def print_descriptions(self):
print('OUTPUT ITEMS\' DESCRIPTIONS')
print('{}\'s Shopping Cart - {}'.format(self.customer_name, self.current_date),end='\n')
print('\nItem Descriptions', end='\n')
for item in self.cart_items:
print('{}: {}'.format(item.item_name, item.item_description), end='\n')
def output_cart(self):
new=ShoppingCart()
print('OUTPUT SHOPPING CART', end='\n')
print('{}\'s Shopping Cart - {}'.format(self.customer_name, self.current_date),end='\n')
print('Number of Items:', new.get_num_items_in_cart(), end='\n\n')
self.total_cost = self.get_cost_of_cart()
if (self.total_cost == 0):
print('SHOPPING CART IS EMPTY')
else:
pass
tc = 0
for item in self.cart_items:
print('{} {} # ${} = ${}'.format(item.item_name, item.item_quantity,
item.item_price, (item.item_quantity * item.item_price)), end='\n')
tc += (item.item_quantity * item.item_price)
print('\nTotal: ${}'.format(tc), end='\n')
def print_menu(ShoppingCart):
customer_Cart = newCart
string=' '
#declare the string menu
menu = ('\nMENU\n'
'a - Add item to cart\n'
'r - Remove item from cart\n'
'c - Change item quantity\n'
'i - Output items\' descriptions\n'
'o - Output shopping cart\n'
'q - Quit\n')
command = ''
#Using while loop
#to iterate until user enters q
while(command != 'q'):
string=''
print(menu, end='\n')
#Prompt the Command
command = input('Choose an option: ')
#repeat the loop until user enters a,i,r,c,q commands
while (command != 'a' and command != 'o' and command != 'i' and command != 'r' and command != 'c' and command != 'q'):
command = input('Choose an option: ')
#If the input command is a
if(command == 'a'):
#call the method to the add elements to the cart
customer_Cart.add_item(string)
#If the input command is o
if(command == 'o'):
#call the method to the display the elements in the cart
customer_Cart.output_cart()
#If the input command is i
if(command == 'i'):
#call the method to the display the elements in the cart
customer_Cart.print_descriptions()
#If the input command is i
if(command == 'r'):
customer_Cart.remove_item()
if(command == 'c'):
customer_Cart.modify_item()
if __name__ == "__main__":
customer_name = str(input('Enter customer\'s name:'))
current_date = str(input('\nEnter today\'s date:'))
print()
print()
print('Customer name:', customer_name, end='\n')
print('Today\'s date:', current_date, end='\n')
newCart = ShoppingCart(customer_name, current_date)
newCart.print_menu(newCart)
i have created an instance of class ShopppingCart but it is not working. i am trying to get a user input and then display the menu for user to choose and implement one of the functions defined in the shopping cart class . Can anyone help me with resolving this issue.

This issue is happening because of function's argument, ShoppingCart. You have called the first argument ShoppingCart, which in reality is the ShoppingCart object; usually this is the self argument. Python does not care what you name it: self, ShoppingCart, corona. The first argument will always be the object that called the function. When calling this function with these lines of code:
newCart = ShoppingCart(customer_name, current_date)
newCart.print_menu(newCart)
you are using the newCart object to call the function and then passing the newCart object as an argument. You don't need to do this. Python already passes the object, so you don't have to.
I'm assuming this is the error you received:
Traceback (most recent call last):
File "c:/Users/jeffg/Desktop/ProgrammingProjects/StackOverFlow/shoppingcart.py", line 246, in <module>
newCart.print_menu(newCart)
TypeError: print_menu() takes 1 positional argument but 2 were given
This error takes place because you're function is defined to only take one argument. You didn't account for the self argument. To fix this, the code would need to be modified to something like this:
def print_menu(self, newCart):
customer_Cart = newCart
Although as discussed before, you don't need the newCart object to be passed, since you already have access to the newCart object with self. You can then slim down the function to this:
def print_menu(self):
And instead of using customer_Cart to call the functions, you can use self:
while (command != 'a' and command != 'o' and command != 'i' and command != 'r' and command != 'c' and command != 'q'):
command = input('Choose an option: ')
if(command == 'a'):
self.add_item(string)
I would also recommend using elif statements instead of using numerous if statements inside your print_menu() function.

Related

Can't correctly call accessor method of class in Python

Here is the code
import random
class Animal(object):
__name = ""
__animal_type = ""
__mood = 0
def __init__(self, animal_type, animal_name):
self.__animal_type = animal_type
self.__name = animal_name
self.__mood = random.randint(1, 3)
def get_animal_type(self, animal):
return self.__animal_type
def get_name(self, animal):
return self.__name
def check_mood(self, animal):
animal_mood = ""
if self.__mood == 0:
animal_mood = "the mood was 0 and didn't change"
elif self.__mood == 1:
animal_mood = "happy"
elif self.__mood == 2:
animal_mood = "hungry"
elif self.__mood == 3:
animal_mood = "sleepy"
return animal_mood
animal_list = [Animal]
do_animal_creation = True
while do_animal_creation:
print("Welcome to animal gen")
new_animal_type = input("What type of animal? ")
new_animal_name = input("Name of animal? ")
new_animal = Animal(new_animal_type, new_animal_name)
animal_list.append(new_animal)
do_animal_creation = input("Add another animal? y/n: ")
if do_animal_creation != 'y':
do_animal_creation = False
print("\nThanks for using this program.")
else:
do_animal_creation = True
print("Animal list:")
for item in animal_list:
item_name = item.get_name(item)
item_type = item.get_animal_type(item)
item_mood = item.check_mood(item)
print(item_name + " the " + item_type + " is " + item_mood + ".")
Everytime I try to call the get_name or get_animal_type or check_mood methods it tells me I'm sending an incorrect amount of parameters. Then I try to play with the parameters, either send one more like it asks me to, or take away a parameter in the method definition within the class, and neither of those work. I feel like I am syntactically not calling the methods correctly, but I don't know what exactly I'm doing wrong.
The first element of your animal_list is the Animal class, not an instance. Hence, calling instance methods on it won't work as expected. Whatever you might have tried to make that work (like passing an instance as first argument) will then fail for the subsequent elements which are instances.
Change
animal_list = [Animal]
# this puts the Animal class in your list
# Note: In Python, lists are not type-parametrized like in other languages,
# which is probably what you assumed you were doing
to
animal_list = []
Moreover, your getters should not take parameters:
def get_animal_type(self):
return self.__animal_type
and call it:
item.get_animal_type()

AttributeError: 'str' object has no attribute 'print_item_cost'

While running this code I am receiving the following error message:
Traceback (most recent call last):
File "main.py", line 33, in <module>
item.print_item_cost()
AttributeError: 'str' object has no attribute 'print_item_cost'
I have verified the attribute is defined in the object, so I am not clear why this error is being thrown.
class ItemToPurchase:
def __init__(self, name = 'none', price = 0, qty = 0):
self.name = name
self.price = price
self.qty = qty
def print_item_cost(self):
print('%s %d # $%d = $%d' % (self.name, self.qty, self.price, (self.price * self.qty)))
def calculate_subtotal(self):
return self.price * self.qty
if __name__ == "__main__":
i = 0
order_list = []
for i in range(2):
print('Item %d' % int(i + 1))
print('Enter the item name:')
input_name = input()
item = input_name
item = ItemToPurchase()
item.name = input_name
print('Enter the item price:')
item.price = int(input())
print('Enter the item quantity:')
item.qty = int(input())
order_list.append(input_name)
print('\nTOTAL COST')
total = 0
for item in order_list:
print(item, '\n')
item.print_item_cost()
total += item.calculate_subtotal()
print('\nTotal: $%d' % total)
The program input I am giving is:
Chocolate Chips
3
1
Bottled Water
1
10
Which should result in the following output:
Item 1
Enter the item name:
Enter the item price:
Enter the item quantity:
Item 2
Enter the item name:
Enter the item price:
Enter the item quantity:
TOTAL COST
Chocolate Chips 1 # $3 = $3
Bottled Water 10 # $1 = $10
Total: $13
You're appending a string, not the item object to the list
input_name = input()
...
order_list.append(input_name)
Then looping over that list, expecting it not to be strings...
I'd recommend cleaning up that section a little so that you actually call the constructor of the class
print('Enter the item name:')
input_name = input()
print('Enter the item price:')
price = int(input())
print('Enter the item quantity:')
qty = int(input())
order_list.append(ItemToPurchase(input_name, price, qty))

Im trying to use the classes that i made(Vehicle and customer), but i get "TypeError: object() takes no parameters". What am i doing wrong?

Im trying to use the classes that i made(Vehicle and customer), but i get "TypeError: object() takes no parameters" every time i try to create ether of this objects. What am i doing wrong?
import sys
import csv
vehicle = 0
customers = []
class Vehicle:
def _init_(self, number, capacity):
self.number = number
self.capacity = capacity
class customer:
def _init_(self, custNo, xCord, yCord, demand, readyT, dueDate, serviceTime):
self.custNo = custNo
self.xCord = xCord
self.yCord = yCord
self.demand = demand
self.readyT = readyT
self.dueDate = dueDate
self.serviceT = serviceTime
def read():
global vehicle
with open('C101 BUENO.csv') as cvs_file:
cvs_reader = csv.reader(cvs_file, delimiter=';')
line = 0
for row in cvs_reader:
print(line)
if line == 0 or line == 2:
line += 1
elif line == 1:
vehicle = Vehicle(row[0], row[1])
line += 1
else:
c = customer(row[0],row[1],row[2],row[3],row[4],row[5],row[6])
customers.append(c)
line += 1
read()

I want to return control to it starting point using function in a class in Python 3

I have 3 different functions in a class if the command in any of the function returns false, I want the program to begin all over again the way it started if the function that returns false was the last command among the function. Also, I want the program to return to the last successful function command if the failed command is not the last among the functions
When I run the program and last function command fails, the program returned to the starting point but ignore certain and crucial part of what I want to achieve, rather it full execute the second function command
class Test():
def greeting(self):
user_input = input("Greeting: ")
print("This is the greeting function")
list1 = ["hello", "Hi"]
if user_input in list1:
print("Thats good")
Test.cities(self)
elif user_input not in list1:
print("Mtchewwww")
Test.greeting(self)
else:
print("be serious")
def cities(self):
print("U re now inside the city function")
list2 = ["Otukpo", "Gboko"]
user_input = input("Cities: ")
if user_input in list2:
print("Nice one")
Test.num(self)
else:
print("that's not a city")
Test.cities(self)
def num(self):
user_input = input("Numbers: ")
list3 = [1, 2, 3, 4]
if int(user_input) in list3:
print("good number")
elif user_input not in list3:
print("That was bad")
Test.greeting(self)
else:
print("Can not compute")
calling = Test()
cal = calling.greeting
cal()
I want the program to behave like this:
if item is in list1 move to the next function but if not in list, try the current function again 3 times and after the the 3 chances and it's still not in the list return to the previous function
def greeting():
user_input = input("Greeting: ")
# It is not good to name your variables like `list1`, `str2`...
# plus, if your list is immutable, use a tuple instead.
options = ('hello', 'Hi')
if user_input in options:
print("That's good")
return True
else:
return False
def cities():
user_input = input("Cities: ")
options = ("Otukpo", "Gboko")
if user_input in options:
print("Nice one")
return True
else:
print("That's not a city")
return False
def num():
user_input = input("Numbers: ")
options = (1, 2, 3, 4)
try:
if int(user_input) in options:
print("Good number")
return True
else:
return False
except ValueError:
# In case that the input is not a number
return False
def main():
fns = (greeting, cities, num)
ptr = 0
cnt = 0
# Just for your information, you don't have to use `ptr >= 0 and ptr <3` in python
while 0 <= ptr < 3:
# print(ptr, cnt)
if cnt >= 3:
# if failed for 3 times, move `ptr` to the previous function, and reset `cnt` to 0
ptr -= 1
cnt = 0
continue
# Get the current function, as `fn`
fn = fns[ptr]
if fn():
# if the current function is a success, move to next, and reset `cnt`
ptr += 1
cnt = 0
else:
# if the current function is a failure, it will be tried again in next while loop
cnt += 1
main()
Use a pointer ptr to iterate over your three functions, and use a variable cnt to limit the failure times. Just try it.
Have fun with python!

How can I get eval() to execute a function I define? [Python]

I have some code that I need to evaluate in python 3.4.1
def foo(bar):
somecode
def myFunction(codeInString):
eval("foo(" + codeInString + ")")
But every time I try to evaluate it, I get an error that says
NameError: name 'foo' is not
When I use 'q Patrick m 1880 1885 2' as input, it should give me back a list of three tuples. Instead I get
File "C:\...\Project 1\names.py", line XXX, in BBNInput
return(eval("getBirthsByName(" + query + ")"))
File "<string>", line 1, in <module>
NameError: name 'getBirthsByName' is not defined
I defined tiny_names.csv below the code block
import matplotlib.pyplot as plt
import string
def names( infile = 'tiny_names.csv'):
#This takes in the name of the file containing the clean name data and returns a list in the format [year, name, sex, quantity]
def readNames(infile = 'tiny_names.csv'):
#Counts the number of name-year combinations
counter = 0
#Opens the file
file = open(infile, 'r')
#Reads each line into an item on the list
names = [i for i in file]
#Formatting
for i in names:
#increments the counter
counter = counter + 1
index = names.index(i)
#Removes the newline char
names[index] = i.strip('\n')
#splits by the comma
names[index] = names[index].split(',')
#reformats the numbers into ints, makes names all lowercase to make searching easier
names[index] = [ int(names[index][0]), names[index][1].lower(), names[index][2], int(names[index][3])]
#closes the file
file.close()
#returns the names
return(names)
#Takes names as an argument and returns a dictionary with keys of names and values of lists of tuples (year, male births, female births)
def nameIndex(names):
#Initialize the empty dictionary
result = {}
for i in names:
name = i[1]
if name not in result.keys():
#if it's a male, add in the male format
if i[2] == 'M':
result[name] = [(i[0], i[3], 0)]
#otherwise, add in the female format
else:
result[name] = [(i[0], 0, i[3])]
#Checking if there is already a datapoint for that year
elif True in [( i[0] == a[0]) for a in result[name]]:
xx = [( i[0] == a[0]) for a in result[name]]
index = xx.index(True)
#If there is a datum in the male slot, add the new datum to the female slot
if result[name][index][1] == 0:
result[name][index] = (result[name][index][0], i[3], result[name][index][2])
#Otherwise, vice versa
else:
result[name][index][2] == (result[name][index][0], result[name][index][1], i[3])
#if the name exists but the year is unique
else:
#if it is a male, add it in the male format
if i[2] == 'M':
result[name].append((i[0], i[3], 0))
#otherwise add it in the female format
else:
result[name].append((i[0], 0, i[3]))
#Return the results
return(result)
def getBirthsByName (name , gender=None, start=None, end=None, interval=None):
#initialize the return variable
thing = []
#Make the name variable auto match the format of the names
name = name.lower()
#if the name doesn't exist, say so
if name not in nameIndex:
return("Name not in index")
#if there are no time constraints
if not start and not end and not interval:
#cycle through the name Data Points (dp) and addup the numbers for
for dp in nameIndex[name]:
year = dp[0]
#Gender neutral
if not gender:
thing.append((year, dp[1] +dp[2]))
#Males
elif gender.upper() == "M":
thing.append((year, dp[1]))
#Females
elif gender.upper() == "F":
thing.append((year, dp[2]))
#Data validation, gender != m or f
else:
return("You have entered and invalid gender, because we are insensitive people")
else:
#Data Validation, see return comments
if interval and (not start or not end):
return("You must have a start and an end to have an interval")
if not end:
end = 2013 #initializes end if blank
if start:
return("You must have a start to have an end")
if not start:
start = 1880 #initializes start if blank
if not interval:
interval = 1 #initializes interval if blank
#If the input passes all the validation tests, return data
for year in range (start, end, interval):
if year not in yearIndex.keys():
continue
if name not in yearIndex.get(year).keys():
continue
#Assign the tuple to dp
dp = yearIndex.get(year).get(name)
#Gender neutral
if not gender:
thing.append((year, dp[0] +dp[1]))
#Males
elif gender.upper() == "M":
thing.append((year, dp[0]))
#Females
elif gender.upper() == "F":
thing.append((year, dp[1]))
return(thing)
def BBNInput(inp):
split = inp[2:].split()
query = '"' + split[0] + '"'
if (split[1] != None):
query = query + ',"' + split[1] + '"'
if (split[2] != None):
query = query + "," + split[2]
if (split[3] != None):
query = query + "," + split[3]
if (split[4] != None):
query = query + "," + split[4]
return(eval("getBirthsByName(" + query + ")"))
#read the names
print("read the names")
nameList = readNames()
#store the name index
print("make the name index")
nameIndex = nameIndex(nameList)
#initialize the exit bool
exit = False
#Functional loop
while not exit:
queue = []
inp = input('names> ')
if inp == 'x':
exit = True
continue
elif inp[0] == 'c':
data = BBNInput(inp)
total = 0
for dp in data:
total = total + dp[1]
print(total)
elif inp[0] == 'q':
print(BBNInput(inp))
elif inp[0] == 'p':
split = inp[2:].split()
query = '"' + split[0] + '"'
if (split[1] != None):
query = query + ',"' + split[1] + '"'
if (split[2] != None):
query = query + "," + split[2]
if (split[3] != None):
query = query + "," + split[3]
if (split[4] != None):
query = query + "," + split[4]
exec("print(getBirthsByName(" +query + "))")
names()
tiny_names.csv =
1890,Patrick,M,227
1890,Mary,F,12078
1890,Charles,M,4061
1890,Alice,F,2271
1889,Patrick,M,236
1889,Mary,F,11648
1889,Charles,M,4199
1889,Alice,F,2145
1888,Patrick,M,245
1888,Mary,F,11754
1888,Charles,M,4591
1888,Alice,F,2202
1887,Patrick,M,218
1887,Mary,F,9888
1887,Charles,M,4031
1887,Alice,F,1819
1886,Patrick,M,249
1886,Mary,F,9890
1886,Charles,M,4533
1886,Alice,F,1811
1885,Patrick,M,217
1885,Mary,F,9128
1885,Charles,M,4599
1885,Alice,F,1681
1884,Patrick,M,222
1884,Mary,F,9217
1884,Charles,M,4802
1884,Alice,F,1732
1883,Patrick,M,213
1883,Mary,F,8012
1883,Charles,M,4826
1883,Alice,F,1488
1882,Patrick,M,249
1882,Mary,F,8148
1882,Charles,M,5092
1882,Alice,F,1542
1881,Patrick,M,188
1881,Mary,F,6919
1881,Charles,M,4636
1881,Alice,F,1308
1880,Patrick,M,248
1880,Mary,F,7065
1880,Charles,M,5348
1880,Alice,F,1414
Well, now I think there is too much code to obviously see what the problem is. However, you probably don't need to even use eval() at all. The following will likely do what you want:
def BBNInput(inp):
split = inp[2:].split()
return getBirthsByName(*split)
See What does ** (double star) and * (star) do for Python parameters? for further information on what this means.
I fixed it by changing my BBNInput function to a query building function and evaluated (using eval()) on the same level as the def for getBirthsByName. But I think that #GregHewgill has the right of it, makes way more sense. Thanks for your help everyone!

Resources