i`m trying to learn classes, and something is holding em back, i get
"NameError: global name 'self' is not defined"
the same happens to each class field. can you help me find what am i doing wrong thank you
Code:
class Assignment:
def __init__(self, name, discription, deadline, grade, studentID):
self.name = name
self.studentID = studentID
self.description = discription
self.deadline = deadline
self.grade = grade
def __str__(self):
return "studentID:" + self.studentID + "assignment name:" + self.name +" description:" + self.description + " deadline:" + self.deadline + " grade:" + self.grade
def validation(self):
errors= []
if self.studendID == "":
errors.append("No existing student ID.")
if self.description == "":
errors.append("No existing description.")
if self.deadline == "":
errors.append("No existing deadline.")
if self.deadline == "":
errors.append("No existing deadline.")
return errors
#staticmethod
def dummyAssignments():
ret = []
for studentID in range(100, 121):
print "sda"
a = Assignment(self, name, discription, deadline, grade, studentID)
ret.append(a)
return ret
def testAssigment():
a = Assignment("","","","","")
print a
testAssigment()
print Assignment.dummyAssignments()
The problem is here:
a = Assignment(self, name, discription, deadline, grade, studentID)
This is in a #staticmethod, so self isn't defined.
Indeed, none of those values are defined, come to think of it -- except studentID.
You don't need to pass self when instantiating your class.
Assignment(self, name, discription, deadline, grade, studentID)
should be
Assignment(name, discription, deadline, grade, studentID)
The error is letting you know you are trying to use a var self that is not defined in either local or global scope.
The dummyAssignments static method only has studentIDs but not any of the other fields.
Try giving default values to each of the fields:
class Assignment:
def __init__(self, name='', discription='', deadline='', grade='', studentID =''):
self.name = name
self.studentID = studentID
self.description = discription
self.deadline = deadline
self.grade = grade
def __str__(self):
return "studentID:" + self.studentID + "assignment name:" + self.name +" description:" + self.description + " deadline:" + self.deadline + " grade:" + self.grade
def validation(self):
errors= []
if self.studendID == "":
errors.append("No existing student ID.")
if self.description == "":
errors.append("No existing description.")
if self.deadline == "":
errors.append("No existing deadline.")
if self.deadline == "":
errors.append("No existing deadline.")
return errors
#staticmethod
def dummyAssignments():
ret = []
for studentID in range(100, 121):
print "sda"
a = Assignment(studentID=studentID)
ret.append(a)
return ret
def testAssigment():
a = Assignment("","","","","")
print a
testAssigment()
print Assignment.dummyAssignments()
in your class decleration:
class Assignment:
change it to
class Assignment():
or
class Assignment(object):
Related
I've created a class named Patient that has attributes for patient information. I'm supposed to use an accessor and mutator method for each attribute. Then I've created another file to access the class and insert patient information to print. Every time I print I don't get what I expect but I get <Assignment4Q1PatientClass2nd.Patient object at 0x000002429E038A00>.
Here's what is on my first file (File name is Assignment4Q1PatientClass2nd):
class Patient:
def __init__(self, fname, mname, lname, address, city, state, zipcode, phone, ename, ephone):
self._fname = fname #first name
self._mname = mname #middle name
self._lname = lname #last name
self._address = address #address
self._city = city #city for address
self._state = state #state for address
self._zipcode = zipcode #zipcode for address
self._phone = phone #phone number
self._ename = ename #emergency name
self._ephone = ephone #emergency phone
#add patient information
def addFirstName(self, firstname):
self._fname = self._fname + firstname
def addMiddleName(self, middlename):
self._mname = self._mname + middlename
def addLastName(self, lastname):
self._lname = self._lname + lastname
def addAddress(self, locaddress):
self._address = self._address + locaddress
def addCity(self, cityname):
self._city = self._city + cityname
def addState(self, statename):
self._state = self._state + statename
def addZipcode(self, zipcodenum):
self._zipcode = self._zipcode + zipcodenum
def addPhone(self, phonenum):
self._phone = self._phone + phonenum
def addEName(self, emergencyname):
self._ename = self._ename + emergencyname
def addEPhone(self, emergencyphone):
self._ephone = self._ephone + emergencyphone
#get/return all information of the Patient
def getPatientFirstName(self):
return "First Name:" + self._fname
def getPatientMiddleName(self):
return "Middle Name:" + self._mname
def getPatientLastName(self):
return "Last Name:" + self._lname
def getPatientAddress(self):
return "Address:" + self._address
def getPatientCity(self):
return "City:" + self._city
def getPatientState(self):
return "State:" + self._state
def getPatientZipcode(self):
return "ZIP:" + self._zipcode
def getPatientPhone(self):
return "Phone:" + self._phone
def getPatientEName(self, emergencyname):
return "Emergency Contact:" + self._ename
def getPatientEPhone(self, emergencyphone):
return "Emergency Phone:" + self._ephone
on the second file is:
from Assignment4Q1PatientClass2nd import Patient
pat = Patient("James", "Edward", "Jones", "345 Main Street", "Billings", "Montanna", 59000, "406-555-1212", "Jenny Jones", "406-555-1213")
print(pat)
What did you expect from your print statement?
The class actually don't "know" what to print. You must provide a way to represent that class as a string, so we can print that string.
In practice, we do this by adding a function called "__repr__", the representation of this class. Python automatically identifies this as a especial one, just like "__init__".
Here is a small example to you:
class Patient:
def __init__(self, name):
self._name = name
def getPatientName(self):
return self._name
def __repr__(self):
return "Hey! My name is " + self.getPatientName()
pat = Patient("Dikson")
print(pat)
# Hey! My name is Dikson
Hope it's clear :)
I have a class (Student) with different attributes, such as studentId, address, and courses. My str method for the class returns all the information that the user put in. However, for the attributes that are lists, such as courses, the location of the information is printed out instead of the actual information. Here is the code (sorry it's a little long, there's a bunch of classes):
class Person:
__name = None
__age = None
__address = None
def __init__(self, name, age=0, address=None):
self.set_name(name)
self.set_age(age)
self.set_address(address)
def __str__(self):
return 'Name: ' + self.__name + '\n' + \
'Age: ' + str(self.__age) + '\n' + \
'Address: ' + str(self.__address)
def set_name(self, name):
self.__name = name
def get_name(self):
return self.__name
def set_age(self, age):
self.__age = age
def get_age(self):
return self.__age
def set_address(self, address):
self.__address = address
def get_address(self):
return self.__address
class Student(Person):
def __init__(self, name, studentID= None, age= 0, address= None):
super(Student, self).__init__(name, age, address)
self.set_studentID(studentID)
self.__courses =[]
def __str__(self):
result = Person.__str__(self)
result += '\nStudent ID:' + self.get_studentID()
for item in self.__courses:
result += '\n ' + str(item)
return result
def set_studentID(self, studentID):
if isinstance(studentID, str) and len(studentID.strip()) > 0:
self.__studentID = studentID.strip()
else:
self.__studentID = 'NA'
def get_studentID(self):
return self.__studentID
def add_course(self, course):
print('in add_course')
self.__courses.append(course)
def get_courses(self):
for i in range(len(self.__courses)):
return self.__courses[i]
class Course:
__courseName = None
__dept = None
__credits = None
def __init__(self, courseName, dept= 'GE', credits= None):
self.set_courseName(courseName)
self.set_dept(dept)
self.set_credits(credits)
def __str__(self):
return self.get_courseName() + '/' + self.get_dept() + '/' + str(self.get_credits())
def set_courseName(self, courseName):
if isinstance(courseName, str) and len(courseName.strip()) > 0:
self.__courseName = courseName.strip()
else:
print('ERROR: Name must be a non-empty string')
raise TypeError('Name must be a non-empty string')
def get_courseName(self):
return self.__courseName
def set_dept(self, dept):
if isinstance(dept, str) and len(dept.strip()) > 0:
self.__dept = dept.strip()
else:
self.__dept = "GE"
def get_dept(self):
return self.__dept
def set_credits(self, credits):
if isinstance(credits, int) and credits > 0:
self.__credits = credits
else:
self.__credits = 3
def get_credits(self):
return self.__credits
students = []
def recordStudentEntry():
name = input('What is your name? ')
age = input('How old are you? ')
studentID= input('What is your student ID? ')
address = input('What is your address? ')
s1 = Student(name, studentID, int(age), address)
students.append(s1)
s1.add_course(recordCourseEntry())
print('\ndisplaying students...')
displayStudents()
print()
def recordCourseEntry():
courses = []
for i in range(2):
courseName = input('What is the name of one course you are taking? ')
dept = input('What department is your course in? ')
credits = input('How many credits is this course? ')
c1 = Course(courseName, dept, credits)
print(c1)
courses.append(c1)
displayCourses(courses)
return courses
def displayCourses(courses):
print('\ndisplaying courses of student... ')
for c in range(len(courses)):
print(courses[c])
def displayStudents():
for s in range(len(students)):
print()
print(students[s])
recordStudentEntry()
This is how the code above prints out the 'displaying students...' part:
displaying students...
Name: sam
Age: 33
Address: 123 st
Student ID:123abc
[<__main__.Course object at 0x000002BE36E0F7F0>, <__main__.Course object at
0x000002BE36E0F040>]
I know that it is printing out the location because I need to index into the list. However, the length of the list will be different every time. Normally if I wanted to index into a list, for example, to print a list of names, I would do:
listOfNames = ['sam', 'john', 'sara']
for i in range(len(listOfNames)):
print(listOfNames[i])
or
listOfNames = ['sam', 'john', 'sara']
for i in listOfNames:
print(i)
(not sure what if any difference there is between the 2 ways since they both print out the same way:)
sam
john
sara
How can I write something like the indexing into a list technique shown here in my str method for my class so that it prints the information and not the location?
It would be good to keep to the standard conventions for Python, such as naming
private attributes for objects with single underscores, not double underscores.
The latter are reserved for Python "internal" attributes and methods.
Also, it is convention to use object attributes for objects with get/set methods,
not class attributes. This will make it easier to inspect your objects, while
still maintaining data hiding. Example:
class Course:
def __init__(self, courseName, dept= 'GE', credits= None):
self._courseName = None
self._dept = None
self._credits = None
self.set_courseName(courseName)
...
Your question about why the courses don't print out the way you expected
is rooted in a programming error with the way you programmed the recording
of courses. In recordCourseEntry(), you record two courses and put them
in a list. However, you pass that to your Student object using a method
intended for one course at a time. My suggested fix would be:
...
# s1.add_course(recordCourseEntry())
courses = recordCourseEntry()
for course in courses:
s1.add_course(course)
...
This will probably be enough to get you going. An example output I got was:
Name: Virtual Scooter
Age: 33
Address: 101 University St.
Student ID:2021
ff/GE/3
gg/GE/3
students = []
class Student:
school_name = 'Maharshi Science school'
def __init__(self,name,student_id=336):
self.name = name
self.student_id= student_id
students.append(self)
def __str__(self):
return "student: " + self.name
def get_name_capitalize(self):
return self.name.capitalize()
def get_school_name(self):
return self.school_name
class HighschoolStudent(Student):
school_name = 'Maharshi High School'
def get_school_name(self):
return "This is a high school student"
def get_name_capitalize(self):
original_value = super().get_name_capitalize()
return original_value + "-HighschoolStudent"
chirag = HighschoolStudent('chirag')
print(chirag.get_name_capitalize())
This error will only occur if you are using Python 2. To fix this, replace
super().get_name_capitalize()
with
super(HighschoolStudent, self).get_name_capitalize()
If you upgrade to Python 3, your code should work fine.
You are getting the error due to Python 2. Please try the below code:
students = []
class Student(object):
school_name = 'Maharshi Science school'
def __init__(self,name,student_id=336):
self.name = name
self.student_id= student_id
students.append(self)
def __str__(self):
return "student: " + self.name
def get_name_capitalize(self):
return self.name.capitalize()
def get_school_name(self):
return self.school_name
class HighschoolStudent(Student):
school_name = 'Maharshi High School'
def get_school_name(self):
return "This is a high school student"
def get_name_capitalize(self):
original_value = super(HighschoolStudent, self).get_name_capitalize()
return original_value + "-HighschoolStudent"
chirag = HighschoolStudent('chirag')
print(chirag.get_name_capitalize())
Output:
Chirag-HighschoolStudent
There are two changes in this:
class Student --> class Student(object)
Passing your class name as input in super as mandated by Python 2
So for my last assingment in my python course at uni, I have to write a program consisting of three objects, two of which inherit. I keep running into a snag especially with regards to the last two objects. Here is my code:
class Course:
def __init__(self,title="",ID=0):
self._ID = ID
self._title = title
def getID(self):
return self._ID
def getTitle(self):
return self._title
def setTitle(self,title):
self._title = title
def setID(self,ID):
self._ID = ID
def __repr__(self):
return "Title: " + self._title + "ID: " + str(self._ID)
class OfferedCourse(Course):
def __init__(self,title="",ID=0,enrollment=[]):
super().__init__(title,ID)
self._enrollment = len(enrollment)
def getEnrollment(self):
return self._enrollment
def addStudent(self,stu):
if stu in enrollment:
print("Student is already enrolled.")
else:
enrollment.append(stu)
def dropStudent(self,stu):
if stu in enrollment:
def __repr__(self):
super().__repr__() + "Enrollment: " + str(self._enrollment)
class StudentCourse(Course):
def __init__(self,grade,ID=0,title=""):
super().__init__(title,ID)
self._grade = grade
def getGrade(self):
return self._grade
def setGrade(self,grade):
self._grade = grade
def __repr__(self):
super().__repr__() + "Grade: " + str(self._grade)
def main():
#Set primary course
lego=Course("Lego Design",32013)
#display course
print(lego)
#Set OfferedCourse
bonk=OfferedCourse("Matoran History",82932,["Josh","Rick","Greg","Chris"])
#Display OfferedCourse
print(bonk)
#Set StudentCourse
lp=StudentCourse("History of Nu-Metal",57859,82)
#display Student Course
print(lp)
At around line 60 I recieve the error:
TypeError: str returned non-string (type NoneType)
I'm pretty lost as to what is going on.
Your __repr__s don't explicitly return anything. You build up a string, then throw it away, causing None to be implicitly returned instead.
Just add a return:
def __repr__(self):
return super().__repr__() + "Grade: " + str(self._grade)
Adjustments to the source code of the original question:
add missing statement at def dropStudent(self,stu):
add missing return expression for def __repr__(self):
adjust signature of StudentCourse(Course) init to def __init__(self,title,ID,grade): to be in line with parent classes and process given statement StudentCourse("History of Nu-Metal",57859,82) as expected
add missing indentions for def main():
class Course:
def __init__(self,title="",ID=0):
self._ID = ID
self._title = title
def getID(self):
return self._ID
def getTitle(self):
return self._title
def setTitle(self,title):
self._title = title
def setID(self,ID):
self._ID = ID
def __repr__(self):
return "Title: " + self._title + "ID: " + str(self._ID)
class OfferedCourse(Course):
def __init__(self,title="",ID=0,enrollment=[]):
super().__init__(title,ID)
self._enrollment = len(enrollment)
def getEnrollment(self):
return self._enrollment
def addStudent(self,stu):
if stu in enrollment:
print("Student is already enrolled.")
else:
enrollment.append(stu)
def dropStudent(self,stu):
if stu in enrollment:
print("#todo Something is missing here...")
def __repr__(self):
return super().__repr__() + "Enrollment: " + str(self._enrollment)
class StudentCourse(Course):
def __init__(self,title,ID,grade):
super().__init__(title,ID)
self._grade = grade
def getGrade(self):
return self._grade
def setGrade(self,grade):
self._grade = grade
def __repr__(self):
return super().__repr__() + "Grade: " + str(self._grade)
def main():
#Set primary course
lego=Course("Lego Design",32013)
#display course
print(lego)
#Set OfferedCourse
bonk=OfferedCourse("Matoran History",82932,["Josh","Rick","Greg","Chris"])
#Display OfferedCourse
print(bonk)
#Set StudentCourse
lp=StudentCourse("History of Nu-Metal",57859,82)
#display Student Course
print(lp)
main()
class Course(object):
def __init__(self,cnum,name):
self.name = name
self.cnum = cnum
def __str__(self):
return 'Course:' , self.cnum , self.name
class AssigendCourse(Course):
def __init__(self,Course,dept,year,semester):
self.name = Course.name
self.cnum = Course.cnum
if dept == 'SE' or dept == 'CE' or dept == 'CIE' or dept == 'ME':
self.dept = dept
else:
self.dept = None
if year >= 1 and year <= 4:
self.year = year
else:
self.year = None
if semester >= 1 and semester <= 3:
self.semester = semester
else:
self.semester = None
def __str__(self):
return 'Course: ' , self.name , self.cnum
results in this type of error
TypeError: __str__ returned non-string (type tuple)
I can't figure what type of syntax I need to use for the __str__ func in order to get the print for the object when using:
it = iter(db)
for i in it:
print(i)
Your __str__ methods return tuples:
def __str__(self):
return 'Course:' , self.cnum , self.name
The comma makes it it tuple.
You'll need to join those values; I recommend string formatting:
def __str__(self):
return 'Course: {} {}'.format(self.cnum, self.name)