I see this question has been asked before in different variations, but I feel as though I have implemented the feedback I have seen in those threads (mainly making sure the object is created as I have done in the second last night, and making sure the dictionary is initiated, which I feel I have done in the third line) and I am still receiving the error. Any advice would be very much appreciated. Thank you!
class Groceries:
def __init__(self, grocery_list):
self.grocery_list = {}
def add_item(self, item):
item = input("name: ")
purchased = input(False)
self.grocery_list[item] = purchased
something = Groceries()
something.add_item()
The error I get is:
Traceback (most recent call last):
File "intermediate_python.py", line 14, in <module>
something = Groceries()
TypeError: __init__() missing 1 required positional argument: 'grocery_list'
I tried to resolve this error by removing grocery_list from the def init statement (not sure why this would work, I was just playing around) and the error was moved to the next line with:
Traceback (most recent call last):
File "intermediate_python.py", line 15, in <module>
something.add_item()
TypeError: add_item() missing 1 required positional argument: 'item'
To initialise an instance of your Groceries class you need to provide the parameter "grocery_list" which is defined in your init method
class Groceries:
def __init__(self, grocery_list):
self.grocery_list = {}
Try create your instance using the following:
something = Groceries({"milk": 1, "butter": 1})
Alternatively, to allow for empty Groceries objects, you can add a default parameter to the init method, you should also be assigning the value of the parameter to the variable self.grocery_list instead of assigning it an empty dictionary:
class Groceries:
def __init__(self, grocery_list={}):
self.grocery_list = grocery_list
and also with your method add_item, again you need to pass a parameter or else removed the parameter (since you're asking for it as input)
def add_item(self):
item = input("name: ")
purchased = input("amount: ")
self.grocery_list[item] = purchased
something = Groceries({"milk": 0})
something.add_item()
>> name:
>>> milk
>> amount:
>>> 1
def __init__(self, grocery_list):
self.grocery_list = {}
Although you are passing a grocery_list to your constructor, you are not actually using it to set the value. You merely need to set self.grocery_list equal to the passed argument grocery_list to fix this as I do below.
def add_item(self, item):
item = input("name: ")
You are also trying to both pass item as an argument and input it manually in the function. This means that regardless of what input you send to add_item, you will always override that value with user input. You can fix this by making the item argument optional and checking if it was passed before prompting the user for input as I do below.
purchased = input(False)
self.grocery_list[item] = purchased
Also, it is unclear here why you are fetching input with an implicit conversion of the boolean value False to string as a second prompt after asking for the item name. It seems that you want to set some purchased value to True or False, but it is also unclear then why you are using a dictionary for making a list of groceries in the first place unless you intend to include the quantity as the dictionary value. If you just wanted to see if an item was on the grocery list you could use the set() type instead of dict(). This might serve as an example to help you move forward if you want to maintain quantities.
class Groceries:
def __init__(self, grocery_list={}):
self.grocery_list = grocery_list
def add_item(self, item='', qty=1):
if not item: item = input('name: ')
if item in self.grocery_list:
self.grocery_list[item] += qty
else:
self.grocery_list[item] = qty
def item_qty(self, item=''):
if not item: item = input('name: ')
return(self.grocery_list[item])
def print_all(self):
for key, val in self.grocery_list.items():
print(val, key)
something = Groceries()
something.add_item('apple') # add one apple to groceries
print(something.item_qty('apple'))
something.add_item('apple', 3) # add three apples to groceries
print(something.item_qty('apple'))
something.add_item() # add arbitrary item to groceries
something.print_all() # print all groceries
If you are creating an instance of the Groceries class (something = Groceries(*args)), at the end of the initialization, the Groceries.__init__() function gets called with the same argument list *args.
That means, when you write something = Groceries(), you are trying to call the __init__ function without arguments. On the other hand, the function has a required positional argument grocery_list (any positional argument is required if you didn't provide a default for it).
Since your code defines the grocery_list as an empty dictionary anyway, you don't need to have this an argument to your __init__ function, you can simply use:
def __init__(self):
self.grocery_list = {}
Which will fix the error.
Or you can have a default value and use:
def __init__(self, grocery_list={}):
self.grocery_list = grocery_list
Which would let you use __init__ without providing the grocery_list argument, and using {} in that case.
The exact same case holds for the add_item function: you are defining it with a required positional argument, and then you are trying to call it without any argument. Since you aren't passing any value to the function on the function call that you would later use, you can again remove the argument and simply use:
def add_item(self):
Related
This code's really unfinished, but it's getting there. I'm trying to organize the inputs of an item's name and price to a list, but I'm getting an error caused by the code looking for the _purchases attribute in the Item class instead of the Receipt class. What's causing this?
import datetime
class Item:
def __init__(self,_name="None",_price=0,_taxable="no"):
self._name=_name
self._price=_price
self._taxable=_taxable
def __str__(self):
base="{:-<20}".format(self._name)+"{:->20}".format(self._price)
return base
def getPric(self):
pass
def getTax(self):
pass
class Receipt:
def __init__(self,_tax_rate=0,_purchases=""):
self._tax_rate=_tax_rate
self._purchases=_purchases
def __str__(self):
pass
def additem(self):
list=self._purchases.append(self)
#Main Program
if __name__=="__main__":
loop="no"
print("Welcome to Receipt Creator")
while True:
name=input("Enter Item name: ")
price=float(input("Enter Item Price: "))
taxable=input("Is the item taxable (yes/no): ")
product=Item(name,price,taxable)
print(product)
print(Receipt.additem(product))
print(list)
loop=input("Add another item (yes/no): ")
if loop=="yes":
continue
else:
break
print("----- Receipt",str(datetime.datetime.now()),"-----")
print(list)
EDIT: Here's the error
Traceback (most recent call last):
File "C:\Users\lucas\Desktop\main.py", line 35, in <module>
print(Receipt.additem(product))
File "C:\Users\lucas\Desktop\main.py", line 23, in additem
list=self._purchases.append(self)
AttributeError: 'Item' object has no attribute '_purchases'
You have a clear idea of what you have, but the execution has a lot of room for improvement.
Let's not touch the Item class, since that is not the one that is causing troubles. But as regards to Receipt, let's create a list for purchases to hold the purchases, and let's define a method (add_item) to populate that list:
class Receipt:
def __init__(self, tax_rate=0):
self.tax_rate = tax_rate
self.purchases = []
def add_item(self, item):
self.purchases.append(item)
Now, you definitely need to instantiate that Receipt class (as opposite as you were doing), so in your main loop you should have something like:
if __name__=="__main__":
print("Welcome to Receipt Creator")
rcpt = Receipt()
while True:
name = input("Enter Item name: ")
price = float(input("Enter Item Price: "))
taxable = input("Is the item taxable (yes/no): ")
product = Item(name, price, taxable)
print(product)
rcpt.add_item(product)
print(rcpt.purchases)
loop = input("Add another item (yes/no): ")
if loop == "yes":
continue
else:
break
print(rcpt.purchases)
Now, some things to note in your previous code:
Unless you want to let other people know that an attribute is meant to be used only inside the definition of a class, there's no actual need to use a leading underscore to name an attribute.
You were trying to print list. Keep in mind that list is a builtin class, so try name your attributes using something different (you can use a trailing underscore, actually. Like list_). Moreover, you were trying to print the list attribute that you had defined in your additem() method, without having instantiated the Receipt class and ask the class for it (with something like instance.list_).
In your __init__ method of the Receipt class that you had defined, you had a default value for _purchases to be "" (an empty string), but that attribute was intended to be a list. (since you were trying to use the append() method after in your additem() method), which makes no sense at all.
#revliscano has an answer that fixes your issues. I will leave the answer to him. I am just going to explain why you got the somewhat confusing error that you got.
looking for _purchases attribute in the Item class
In your class Receipt you have:
class Receipt:
...
def additem(self):
list=self._purchases.append(self)
and were later calling it with:
product=Item(name,price,taxable)
print(product)
print(Receipt.additem(product))
So you are calling additem() on the Receipt class, not on an instance of that class. Normally when you call an instance method, the instance you are calling it with is passed in as the self by python. It did not have an instance since you called it on the class itself, and as a result under the hood python was passing the product in as the self variable because python was treating it like a call on a static class method though it was supposed to be an instance method (i.e. no cls or self arg, and just pass the given arg to the method). So because you called it like Receipt.additem(product), the product was passed as the self.
That meant that when it tried to do the self._purchases.append(self) it was like it was trying to do product._purchases.append(product) and so it was trying to find the _purchases attribute on product. Since product is an instance of the Item class, that is how you get your confusing error message.
The below python class have empty dictionary as initial arguments, after calling
createAccount() outside class it successfully add data to dictionary but I can't access dictionary outside class.
What changes shall I make in the below code to access the newly created account details ?
*Please note that my error occurs in the last line of the code *
class SavingsAccount():
def __init__(self):
self.savingsAccounts = {}
def createAccount(self, name, initialDeposit):
print()
self.accountNumber = int(12345)
self.savingsAccounts[self.accountNumber] = [name, initialDeposit]
print("Account creation has been successful. Your account number is ", self.accountNumber)
SavingsAccount().createAccount(name = 'a',initialDeposit=4)
print(SavingsAccount().savingsAccounts[12345]) # getting error here
You should initialize your object using __init__,
class SavingsAccount:
def __init__(self, name, initial_deposit):
self.accountNumber = 12345
self.savingsAccounts = {self.accountNumber : [name, initial_deposit] }
print("Account creation has been successful. Your account number is ", self.accountNumber)
saving_account = SavingsAccount(name='a', initial_deposit=4)
print(saving_account.savingsAccounts)
Also, most of the Pythonistas prefer snake_casing while naming variables.
You are creating a new instance of SavingsAccount with every call. After you call to createAccount completes, that instance is garbage-collected, as there are no references to it stored anywhere.
s = SavingsAccount()
s.createAccount(name='a', initialDeposit=4)
print(s.savingsAccounts[12345])
(See Taohidul Islam's answer for how you should be defining the class, though.)
The line that gives the error does this actions:
Calls SavingsAccount.init() to create the object
Asks for the item 12345 in the dictionary (that whas just created so it's empty)
You should structure your code in a different way. You should have a list of accounts or similar that is unique, and then insert in it the accounts you create.
Must first initialize an instance of your SavingsAccount class
#initialize savings account object
s = SavingsAccount()
#call created account method
s.createAccount(name="a", initialDeposit=4)
#print the account
print(s.savingsAccounts[12345])
Although your datastructure is confusing, why not have one instance of a savings account object represent an individuals account? Then you could just assign member variables for values you want to track.
class SavingsAccount:
def __init__(self, name, initial_deposit):
self.account_name = name
self.bal = initial_deposit
def deposit(self, val):
self.bal += val
def return_account(self):
return self.__dict__
Now you can use it more simplistically
s = SavingsAccount("name", 500)
s.deposit(500)
acc = s.return_account()
print(acc)
>> {"account_name": "name", "bal": 1000}
I'm programming a store management system in python using sqlite as database. I want to be able to see Item price when the name of the item is entered instead of the Item id...below is the code snippet
def ajax2(self, *args, **kwargs):
self.get_name = self.entername_e.get()
#get the products info with that name or id and fill labels above
query = "SELECT * FROM inventory WHERE name=?"
result = c.execute(query, (self.get_name, ))
for self.r in result:
self.get_name = self.r[1] #name
self.get_price = self.r[4] #sp
self.get_stock = self.r[2] #stock
self.productname.configure(text="Product's Name: "+ str(self.get_name))
self.pprice.configure(text="Price: Gh "+str(self.get_price))
Anytime I run the code after entering the name in the label Entry, the name appears even if it's not in the database and an error message follows in the command line like below:
Exception in Tkinter callback
Traceback (most recent call last):
File "C:\Users\GH\AppData\Local\Programs\Python\Python38\lib\tkinter\__init__.py", line 1883, in
__call__
return self.func(*args)
File "main.py", line 96, in ajax2
self.pprice.configure(text="Price: Gh "+str(self.get_price))
AttributeError: 'Application' object has no attribute 'get_price'
PS C:\Users\GH\Desktop\Developments\Store Management Software>
If the name is not present in the database, the cursor returned by the query is empty and the loop is not entered. As a result, self.get_name is unchanged and keeps the entered value, and self.get_price is not set, hence the error.
You shoud explicitely test for that case:
...
result = c.execute(query, (self.get_name, ))
empty = True
for self.r in result:
empty = False
self.get_name = self.r[1] #name
self.get_price = self.r[4] #sp
self.get_stock = self.r[2] #stock
if empty: // name is not present in database
...
I don't think that you understand the object oriented approach in this python code. The self keyword is used to access the underlying object, of which all the attributes should be defined in the init function of the class. These attributes should only be there to represent the state of an instantation of the class. See this link : link
You should always be careful when altering objects by accessing the attributes directly. A common practice is to only access them by getters and setters, e.g.
def getAttribute_1(self):
return self.attribute_1
There are lots of good books and tutorials about object oriented programming available if you want to learn more about it, just google it.
In this case, for example, I don't see why you do:
for self.r in result: ...
when you should let go off the self keyword:
for r in result: ...
As this result variable is only relevant within the scope of your function.
Furthermore, if you want to set the price attribute of your current object, you should define that attribute in the init function:
def __init__(self, ...)
self.price = 0 """or whatever default value
you want to give it, or initiate it by giving the initial
value as an argument for the constructor"""
maybe define a getter and setter like this:
def get_price(self):
return self.price
def set_price(self, new_price):
self.price = new_price
Then use these methods in your ajax function. Just remember to make a distinction between local variables, e.g. price = result[4] which are only relevant in this function, and attributes of your object, like self.price! These are 2 very different concepts.
To respond to your error in this example: the get_price is not set if the results returned by the query are None, in which case the loop will not be entered. In this case, the self.get_price attribute of you object has never been created, hence the error.
Hope this helps
Here is Customer class:
class Customer:
def __init__(self, timestamp, cid, item_count):
self.time_stamp = timestamp
self.customer_name = cid
self.item_count = item_count
def checkout(self, new_timestamp):
self.time_stamp = new_timestamp
def get_cus_name(self):
return self.customer_name
If I create an empty list of Customer objects like:
customers = [Customer]
And then somewhere else I try to call Customer methods in a loop like:
def checkout_customer(self, cid):
for cus in self.customers:
if cus.get_cus_name == cid:
cus.checkout(self.cur_num_customers + 7)
why do I get an error when I try to call cus.checkout? My ide tells me that it expects a Customer but got an int. Why doesn't it pass itself into the 'self' arg here?
However if I just create a Customer object and directly call its methods, it works fine:
def foo(self):
cus = Customer(1,'pop',2)
cus.checkout(23)
This is my first time learning python, and ive been stuck trying to figure out lists, and accessing its members. Perhaps my initialization of self.custormers = [Customer] is incorrect?
EDIT:
In my constructor of tester class I create an empty list like this:
self.customer = [Customer]
I am able to add customers no problem:
def add_custormer(self, customer):
self.customers.append(customer)
My problem is not adding customers, but accessing their methods once they are in a list. Doing something like this self.customers[0].checkout(1,'pop',2) gives me an error "Expected type 'Customer' got int".
I am not sure of the class where checkout_customer lives but I am assuming you declare the list self.customers somewhere in it.
self.costumers = []
If you intend to add an element Customer to the list you should use something like: self.customers.append(Customer(x,y,z)) since you want to add a new customer to the list and when doing so you are required to initialize the Customer class.
I didn't try the code but I believe something like this should work:
def foo(self):
self.customers.append(Customer(1,'pop',2))
self.checkout_customers(23)
I am a novice in Python and I was trying to program a game like Adventure.
I created a class called Room. In this class there is a function called ask_something in which I can pass a question and as many list as I want for the possible answers. Lists contain the possible answer and the effect of that answer which is another function.
How can I call that function whithin the Room class without knowing what function is it?
this is the code:
class Room:
def ask_question(self, *arg):
self.question = arg[0]
self.answer_options = arg[1:]
for option in self.answer_options:
print '[{}] {}'.format(self.answer_options.index(option), option[0])
answer = raw_input('> ')
self.answer_options[int(answer)][1]()
def print_this(text):
print text
Room.ask_question(
'How are you?',
('Fine!', print_this('ok')),
('Not fine!', print_this('I\'m sorry'))
)
The Python console says
File "room.py", line 13, in ask_question
do_something = self.answer_options[int(answer)][1]()
TypeError: 'NoneType' object is not callable
You are executing/calling the print_this function and passing the return value of executing the function rather than passing the function itself.
Also, you're not creating an instance of the Room class-- you're calling ask_question as a static method.
What you want is something like this:
Room().ask_question(
'How are you?',
('Fine!', print_this, ('ok',)),
('Not fine!', print_this, ('I\'m sorry',))
)
def ask_question(self, *arg):
#... some logic missing... need to handle looping through `arg` here
# but as an example...
# first arg is the first tuple-- ('Fine!', print_this, ('ok',))
# 2nd element of this tuple is the print_this function
# 3rd element of this tuple are the args to pass to the function
do_something = arg[1][1]
do_something_args = arg[1][2]
do_something(*do_something_args)