1

I am a beginner in python and I am having trouble understanding classes. I have a task that requires me to create a class that should return a students information e.g. name, id, age and marks. I have made a class but am having trouble with the output and keep on getting an attribute error:

print("Student: " + self.name + " ID: " + self.ID + " Age: " + self.age + " Mark: " + self.mark)
AttributeError: 'Student' object has no attribute 'age'

I was wondering if someone could explain what I am doing wrong here as I am quite lost.

Rest of the code:

import random
class Student:
 def __init__(self, name, ID):
 self.name = name
 self.ID = ID
 def setAge(self, age):
 self.age = age
 self.age = random.randint(0, 100)
 def setMarks(self, marks):
 self.marks = marks
 self.marks = random.randint(0, 100)
 def Display(self):
 print("Student: " + self.name + " ID: " + self.ID + " Age: " + self.age + " Mark: " + self.mark)
student = Student("John", "ID123")
student.Display()
liborm
2,73423 silver badges33 bronze badges
asked Jan 14, 2020 at 21:55
5
  • You didn't set an age or marks before displaying the info... Commented Jan 14, 2020 at 21:57
  • Yes, because you never set an age for your student. Commented Jan 14, 2020 at 21:57
  • Thank you I just saw the issue as well thanks for the prompt replies! Commented Jan 14, 2020 at 21:59
  • In setAge(), what is the point of self.age = age, given that you immediately re-assign self.age to a random number anyway? Commented Jan 14, 2020 at 21:59
  • Add self.age = None and self.mark = None to the __init__ function. Commented Jan 14, 2020 at 22:02

6 Answers 6

2

You didn't call student.setMarks() and student.setAge() , so marks and age attributes are not created in object yet.

The solution is to call these two methods before calling student.Display()

answered Jan 14, 2020 at 21:59
Sign up to request clarification or add additional context in comments.

1 Comment

Thanks for the quick answer that worked perfectly for me
2

Python objects are a container that has attributes you can set. If you don't set an attribute but try to read it, you get an AttributeError, meaning that the attribute you are looking for does not exist.

Currently, student = Student(...) calls Student.__init__, which assigns the name and ID attribute of the object. You never call student.setAge or student.setMarks, so your object's age and marks attributes are never set and can not be accessed.

It is traditional to assign default values in the __init__ method if you want to generally avoid unexpected crashes like that.

Another thing is that rather having getter and setter methods, as Java would, for example, Python encourages the use of properties. Properties are objects in the class template that can be accessed like a normal attribute, but allow you to run arbitrary code in place of the access and assignment operators.

Putting all that together, you could write something like

class Student:
 def __init__(self, name, ID, age=None, marks=None):
 self.name = name
 self.ID = ID
 self.age = random.randint(0, 100) if age is None else age
 self.marks = random.randint(0, 100) if marks is None else marks
 @property
 def marks(self):
 return self._marks
 @marks.setter
 def marks(self, value):
 # Example of a check you could do
 if not isinstance(value, int):
 raise TypeError('Marks must be an integer')
answered Jan 14, 2020 at 22:01

Comments

1

In your example, you try to access the variable, before the assignment. You would actually have to call student.setAge and student.setMarks with arguments.

On the other note, in your function setAge you instantly overwrite the value, so consider removing either first or second assignment:

def setAge(self, age):
 self.age = age # first assignment
 self.age = random.randint(0, 100) # second assignment
answered Jan 14, 2020 at 22:00

Comments

0

The age attribute is not set because it was never assigned:

student = Student("John", "ID123")
student.setAge(30) # John is 30 years old.
student.Display()
answered Jan 14, 2020 at 21:59

1 Comment

And while that solves the issue, and is certainly fine for this assignment, I want to add that this is somewhat poor design: If EVERY student has an age, it should be a required argument in the constructor.
0

def __init__() works like a constructor. Try to include age attribute inside the __init__() function, call setAge() from __init__(), or setAge() explicitly before calling Display().

Good luck :)

answered Jan 14, 2020 at 22:01

Comments

0

A simpler version for your code:

import random
class Student:
 def __init__(self, name, ID):
 self.name = name
 self.ID = ID
 self.age = random.randint(0, 100)
 self.marks = random.randint(0, 100)
 def Display(self):
 print("Student: " + str(self.name) + " ID: " + str(self.ID) + " Age: " + str(self.age) + " Mark: " + str(self.marks))
student = Student("John", "ID123")
student.Display() 
answered Jan 14, 2022 at 20:05

Comments

Your Answer

Draft saved
Draft discarded

Sign up or log in

Sign up using Google
Sign up using Email and Password

Post as a guest

Required, but never shown

Post as a guest

Required, but never shown

By clicking "Post Your Answer", you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.