I'm trying to change a specific part of an object. Specifically, I'm trying to subtract a certain value from the acc. Where then the change is recorded on an already created text file.
Traceback (most recent call last):
File "main.py", line 152, in <module>
start()
File "main.py", line 141, in start
withdraw(id,input("How much do you want to withdraw?"))
File "main.py", line 55, in withdraw
if allCustom[d].hkid== x:
TypeError: list indices must be integers or slices, not Customer
class Customer:
def __init__(self, name, date, address, hkid, acc):
self.name = name
self.date = date
self.address = address
self.hkid = hkid
self.acc = acc
allCustom = [customer1, customer2, customer3, customer4, customer5]
customer1 = Customer ("Sarah Parker","1/1/2000","Hong Kong, Tai Koo,Tai Koo Shing Block 22,Floor 10, Flat 1", "X1343434","2222")
def withdraw (x,y):
global allCustom
count = 0
for d in allCustom:
if allCustom[d].hkid== x:
if int(allCustom[d].acc) >= int(y):
allCustom[d] = Customer (allCustom[d].name, allCustom[d].date, allCustom[d].address, allCustom[d].hkid, str(int(allCustom[d].acc)-int(y)))
print("Success! Please collect your money.")
break
else:
print("Sorry but you have inseffecient funds to withdraw $"+y)
elif count == len(allCustom):
print("Your HKID does not match any account in our database. Returning to starting screen")
else:
count +=1
def UpdateFile():
global allCustom
OutFile=open("CustomInfo.txt", "w")
for c in allCustom:
OutFile.write(f"\nName:{c.name}\n")
OutFile.write(f"Birth Date:{c.date}\n")
OutFile.write(f"Address:{c.address}\n")
OutFile.write(f"HKID:{c.hkid}\n")
OutFile.write(f"Account value:{c.acc}\n")
OutFile.close()
UpdateFile()
As #furas said in a comment, just use:
if d.hkid== x:
This is because for d in allCustom: will iterate over the list allCustom binding the variable d to each item of the list in turn. At this point d is a Customer object and you can access its attributes. You therefore do not need to try to lookup the customer in the list because you already have a reference to it in d.
You will need to correct the other instances of allCustom[d] in the rest of your code.
You probably have this confused because of this Python idiom:
for i in range(len(allCustom)):
if allCustom[i].hkid== x:
which uses indices to access the items in the list. The first form for d in allCustom is preferred - it is clearer and more succinct.
Related
First of all, I am writing a code to print inventory of Ikea from a file that has lines like this,
F,301.841.73,9.99,HOLMÖ,Floor lamp - gives a soft mood light,none,75,116,22,2.2
where the third one "9.99" is the price of that furniture item. i have getter and setter for the price variable as well.
def setPrice(self, f_price):
self.__price = f_price
def getPrice(self):
return self.__price
there is main class called Furniture and other sub-classes for items like "BED", "NIGHTSTAND", "ARMCHAIR" etc..
there is a UNIT test framework for these classes. where it creates a list, them opens the file and using loop , it adds all the variables for furniture item like type, an article number, a price, a Swedish-sounding name, a basic description, and optionally, a colour from Furniture class as well as sub variables from sub class to list.
then, AT last, we need to count Total value of inventory. where I initialized a Total_value variable to 0.
total_value = 0
for furniture_item in inventory:
print(str(furniture_item)) # print the item
print("="*30) # print a separator
# ADD THE PRICE OF THE ITEM TO THE ACCUMULATOR VARIABLE
total_value += (value)
when I try to get price from getPrice function:
price = Furniture.getPrice
total_value += price
it gives me error like this:
*****Error***
Traceback (most recent call last):
File "__tester__.python3", line 212, in <module>
total_value += price
TypeError: unsupported operand type(s) for +=: 'int' and 'function'**
when i do like this:
Furniture.getPrice = price
total_value += price
It gives me the value of **Total Inventory Value: 3184.0**. But, the value expected is **Total Inventory Value: 1432.91**, I don't know what wrong I am doing.
If anyone can suggest to me how to get this expected value, that would be great!!!
I'm guessing you want
total_price += furniture_item.getPrice()
I wrote a simple Python script to determine if all students grades are reported. The script first loops through and adds students to arrays regarding grade status. Then I loop through the file again, to determine if each students grades are in. I end up with three arrays that include students with "all grades reported", "some grades reported", "no grades reported". However, I want tackle this problem with more of a object oriented approach. I have attempted to create a class that works. I am stuck at how to loop through and create one Object for each student, then use addcourse to push each course into the Object. Any help I can get to become a better programmer would be great!
Data:
**id,fname,lname,course,grade,mode**
10001,Freddy,Freshman,Art-101,A,online
10001,Freddy,Freshman,Art-101,A,online
10002,Suize,Sophmore,Mat-102,C,inperson
10002,Suize,Sophmore,Bio-101, ,inperson
10002,Suize,Sophmore,Soc-201,D,online
10003,Jilly,Junior,mth-102, ,inperson
10003,Jilly,Junior,Bus-101, ,inperson
10003,Jilly,Junior,Che-204, ,inperson
Working Code:
fh = open('students.txt').readlines()
header = fh.pop(0)
gradereported = []
nogradereported = []
for line in fh:
students = line.split(',')
ids = students[0]
grade = students[4]
if grade != "":
gradereported.append(ids)
else:
nogradereported.append(ids)
allgradesin =[]
nogradesin = []
somegradesin = []
for i in fh:
students = line.split(',')
ids = students[0]
if ids in gradereported and ids not in nogradereported:
if ids not in allgradesin:
allgradesin.append(ids)
elif ids not in gradereported and ids in nogradereported:
if ids not in nogradesin:
nogradesin.append(ids)
elif ids in gradereportedand and ids in nogradereported:
if ids not in somegradesin:
somegradesin.append(ids)
Attempt at class:
class Student(object):
def __init__(self, lname, fname, term, courses = []):
self.studid = studid
self.lname = lname
self.fname = fname
self.term = term
self.courses = []
def addcourse(self, course, grade, mode):
self.course = course
self.grade = grade
self.mode = mode
self.courses.append((self.course, self.grade, self.mode))
You could do this, as #blade suggests, by creating a dictionary indexed by student id and then for each row of your input file either get the existing student from the dictionary if it exists or create a new one. In code, this would look like:
class Student(object):
def __init__(self, student_id, lname, fname):
self.studid = student_id
self.lname = lname
self.fname = fname
self.courses = []
def addcourse(self, course, grade, mode):
self.courses.append((course, grade, mode))
students = {}
fh = open('students.txt').readlines()
header = fh.pop(0)
for line in fh:
row = line.split(',')
if len(row) < 6:
continue
student_id, fname, lname, course, grade, mode = [i.strip() for i in row]
student = students.get(student_id, Student(student_id, lname, fname))
student.addcourse(course, grade, mode)
students[student_id] = student
A couple of things to note. First, I modified the constructor of your Student class, dropping the term argument since it wasn't clear where the term was specified in your input file. Furthermore, since you don't use the courses argument I dropped that as well. (Note that you probably don't want to use [] as a default argument. Read about mutable default arguments here.) You also don't need to create instance variables for the course, grade, and mode in your addcourse function, you can just append them directly to the array.
I also added a call to strip for each of the items pulled from the input file to clean up the newlines at the end of each row.
How about this:
Add a dict that id is the key, and the Student object is the value
Loop the file and if the key is in the dict, get the Student object from the dict. Otherwise create a new Student object. Then add the course to the Student object.
In addition to the answer of #JCVanHanne you could define another function in your class to collect the info, whether a student has none, some or all of his/her grades.
One possible way (assuming a missing grade is represented by an empty string while also grades like A+ or other none-empty values are possible) could be:
def gradeStatus(self):
miss = [course[1] for course in self.courses].count("") # count empty grades
if len(self.courses) == miss:
print('No grades at all')
elif miss in range(1, len(self.courses)):
print('Some, but not all grades')
elif miss == 0:
print('All grades provided')
else:
print('Invalid Data')
You probably would use status codes or other ways (like a return value to further process) to work with the information than just printing them. As an example with the print commands:
students['10003'].gradeStatus() # leads to: No grades at all
I have been fiddling around trying to make a personal organizer. Each day is rendered as an object containing the number of hours spent on several given activities. It also, ideally, allows the user to save this info to a file and to import from previous entries.
Here is the code:
class Day:
def __init__(self, date, hours, python, math, story, phil, medi):
self.date = int(date)
self.hours = float(hours)
self.python = float(python)
self.math = float(math)
self.story = float(story)
self.phil = float(phil)
self.medi = float(medi)
def getDay(self):
return repr((self.date, self.hours, self.python, self.math, self.story, self.phil, self.medi))
def getDayList(self):
return list(self.date, self.hours, self.python, self.math, self.story, self.phil, self.medi)
def getInfo():
#the following allows the user to import an existing file with one object per line
question = input("Enter new information or import an existing file(new/imp)")
if question[0] == "i" or question[0] == "I":
fileName = input("What is the name of the file you would like to import?")
inFile = open(fileName, "r")
dayList = []
for line in inFile:
dayList.append(line)
print(dayList)
return dayList
inFile.close()
#the following allows the user to write objects to a new file or append objects to an existing file
#though I have not tested the latter feature
elif question[0] == "n" or question[0] == "N":
question2 = input("Would you like to append this new info to an existing file or write it to a new file(a/w)? Hit blank ente to exit")
fileName = input("Enter filename for new information")
outFile = open(fileName, question2)
dayList = []
while question2 != "":
date = input("Please enter date (in single string)")
hours = input("please enter total hours for the day")
python = input("please enter total hours of python")
math = input("please enter total hours of math")
story = input("please enter total hours of story writing")
phil = input("please enter total hours of philosophy")
medi = input("please enter total hours of meditation")
#creates object
dayObject = Day(date, hours, python, math, story, phil, medi)
dayList.append(dayObject)
question2 = input("Would you ;like to enter more info now (enter 'yes' or hit blank enter to conclude)")
#writes each object to the file
for item in dayList:
print(item, file=outFile)
return dayList
outFile.close()
def main():
dayList = getInfo()
test = dayList[0]
print(test)
print(test.getDay())
main()
When I create a new file, I can use methods on the object: getDay(), for example, returns the various aspects of the class (date, hours, python, etc.). When I import the same file using the code in the first half of the getInfo() function, however, I get this error message:
Traceback (most recent call last):
File "/Users/rainydaycart/Documents/po2.py", line 101, in <module>
main()
File "/Users/rainydaycart/Documents/po2.py", line 98, in main
print(test.getDay())
AttributeError: 'str' object has no attribute 'getDay'
When I print the newly made object it appears to be an object and not a string. Why can't I execute the getDay() method, which is part of the class definition, when I import the same object from the file?
p.s. indents appear to be a little screwey in this post with the function heads(modules?), but they are not a problem when I run the file.
When you do something like -
for item in dayList:
print(item, file=outFile)
You are not actually writing the objects, you are just writing the str(object) for it , and in your case, since your class does not define __str__() or __repr__() , it would be writing -
<__main__.Day object at 0x00260F10>
Simple Example to show this -
>>> class CA:
... pass
...
>>> with open('a.txt','w') as f:
... print(c,file=f)
...
File at the end contains -
<__main__.CA object at 0x00260F10>
What you actually want to use is - pickle module for object serialization and deserialization.
Then you can write an object to file using pickle.dump() and load it using - pickle.load() .
Example -
>>> class CA:
... pass
...
>>> c = CA()
>>> c.x = 10
>>> import pickle
>>> with open('a.txt','wb') as f:
... pickle.dump(c,f)
...
>>> del c
>>> with open('a.txt','rb') as f:
... d = pickle.load(f)
...
>>> d
<__main__.CA object at 0x007150F0>
>>> d.x
10
In main(), shouldn't it be:
def main():
object = Day()
dayList = object.getInfo()
test = dayList[0]
Also, your outFile.close() and inFile.close() don't ever hit, as they are after the return().
When the user enters an email address, and the program reads the email and display it according to its criteria (e.g yeo.myy#edu.co), like criteria:
username is yeo.myy
domain is edu.co
I know its something to do with the "#".
this is the code
class Email:
def __int__(self,emailAddr):
self.emailAddr = emailAddr
def domain(self):
index = 0
for i in range(len(emailAddr)):
if emailAddr[i] == "#":
index = i
return self.emailAddr[index+1:]
def username(self):
index = 0
for i in range(len(emailAddr)):
if emailAddr[i] == "#" :
index = i
return self.emailAddr[:index]
def main():
emailAddr = raw_input("Enter your email>>")
user = Email(emailAddr)
print "Username = ", user.username()
print "Domain = ", user.domain()
main()
this is the error I got:
Traceback (most recent call last):
File "C:/Users/Owner/Desktop/sdsd", line 29, in <module>
main()
File "C:/Users/Owner/Desktop/sdsd", line 24, in main
user = Email(emailAddr)
TypeError: this constructor takes no arguments
def __int__(self,emailAddr):
Did you mean __init__?
def __init__(self,emailAddr):
You're also missing a couple selfs in your methods, and your returns are improperly indented.
def domain(self):
index = 0
for i in range(len(self.emailAddr)):
if self.emailAddr[i] == "#":
index = i
return self.emailAddr[index+1:]
def username(self):
index = 0
for i in range(len(self.emailAddr)):
if self.emailAddr[i] == "#" :
index = i
return self.emailAddr[:index]
Result:
Username = yeo.myy
Domain = edu.co
Incidentally, I recommend partition and rpartition for splitting a string into two pieces on a given separator. Sure beats keeping track of indices manually.
def domain(self):
return self.emailAddr.rpartition("#")[2]
def username(self):
return self.emailAddr.rpartition("#")[0]
This error may happen if you type def _init_ with a single underline instead of def __init__ with double underlines before and after init.
class Employee:
def __init__(self,Name,Age,Salary,Gender):
self.Name = Name
self.Age = Age
self.Salary= Salary
self.Gender = Gender
def show_employee_deatils(self):
print("Name of the employee is ",self.Name)
print("Age of the employee is ",self.age)
print("Salary of the employee is ",self.salary)
print("gender of the employee is ",self.gender)
e1 = Employee('Shubham',25,25000,'male')
e1. show_Employee_deatils( )
I am having problem getting this piece of code to run. The class is Student which has a IdCounter, and it is where the problem seems to be. (at line 8)
class Student:
idCounter = 0
def __init__(self):
self.gpa = 0
self.record = {}
# Each time I create a new student, the idCounter increment
idCounter += 1
self.name = 'Student {0}'.format(Student.idCounter)
classRoster = [] # List of students
for number in range(25):
newStudent = Student()
classRoster.append(newStudent)
print(newStudent.name)
I am trying to have this idCounter inside my Student class, so I can have it as part of the student's name (which is really an ID#, for example Student 12345. But I have been getting error.
Traceback (most recent call last):
File "/Users/yanwchan/Documents/test.py", line 13, in <module>
newStudent = Student()
File "/Users/yanwchan/Documents/test.py", line 8, in __init__
idCounter += 1
UnboundLocalError: local variable 'idCounter' referenced before assignment
I tried to put the idCounter += 1 in before, after, all combination, but I am still getting the referenced before assignment error, can you explain to me what I am doing wrong?
The class variable has to be accessed via the class name, in this example Studend.idCounter:
class Student:
# A student ID counter
idCounter = 0
def __init__(self):
self.gpa = 0
self.record = {}
# Each time I create a new student, the idCounter increment
Student.idCounter += 1
self.name = 'Student {0}'.format(Student.idCounter)
classRoster = [] # List of students
for number in range(25):
newStudent = Student()
classRoster.append(newStudent)
print(newStudent.name)
Thanks to the point out by Ignacio, Vazquez-Abrams, figured it out...
Coming to this answer some time ago helped me find what I needed to sort out class versus instance variables and their scoping.
So, an extension, which does the same thing, only using a generator. The generator assigns a unique number to the student as idCounter does -- only it consumes the values. There is no prev method on the generator class, of which I'm aware. Neither idGenerator nor idCounter is memoized, so if you want to externalize the list then come back to add one or more students, you'd have to update the range(start,,) accordingly, or iterate through each value without assigning it until you arrive at the unique one in sequence, a path somewhat shorter with idCounter which you cou simply set with a single dummy instance construct and go.
class Student:
""" Implement a shared generator among all sub-classes
in addition to idCounter. """
# A student ID counter
idCounter = 0
# A student ID from generator
idGenerator = (x for x in range(0xAAAAAA, 0xEEEEEE, 0xBA))
def __init__(self):
self.gpa = 0
self.record = {}
# Each time I create a new student, the idCounter increment
Student.idCounter += 1
self.id = Student.idGenerator.__next__()
self.name = f"{self.id} Student {Student.idCounter}"
classRoster = [] # List of students
for number in range(25):
newStudent = Student()
classRoster.append(newStudent)
print(newStudent.name)