I have a class that inherits another class in the following manner for some reasons (for example)
class student():
def __init__(self,Name_,Grade_):
self.Name=Name_
self.Grade_=Grade
#Some other code
class Classroom(student):
def __init__(self,Class_Name_,Class_Supervisoir_,list_of_students_Names_,
List_of_Students_Grades_):
self.Class_Name=Class_Name_
self.Class_Supervisoir=Class_Supervisoir_
self.list_of_students_Names=list_of_students_Names_
self.List_of_Students_Grades=List_of_Students_Grades_
for _,__ in enumerate(self.List_of_Students_Grades):
exec("self.Student_"+str(__)+"=student("+str(__)+","+str(
self.List_of_Students_Grades[_])+")"
I want to create a number of instances form the class "student", but as a part of the class "Classroom" i.e can be referenced as in self.student.
Yet I don't know the number of the students entered (which can be many), I want to create an object for each one of them like:
self.Student_Mark=student(mark,20)
self.Student_Peter=student(peter,15)
...
and so on.
The problem then is that I want to make an assignment statement like the ones above but I cant do it without using the exec() function,I have read about the security dangers of using exec() function in production level, so can how can I replace exec() here with something does the same functionality?
2 Answers 2
I don't know why you'd want to name your attributes as such. But you can use setattr. Also I don't think this is a good usecase for throwaway variables, instead you can write:
for ix, name in enumerate(self.List_of_Students_Grades):
setattr(
self,
f"Student_{name}",
student(name, self.List_of_Students_Grades[index])
)
1 Comment
Bit of a framing question: Why is a Classroom a subclass of student? A classroom is a room, but more to the point, a classroom (can't really call it class for obvious reasons) represents a group of students, a teacher/supervisor, and a name. So make a group of students, rather than a variable for each student:
class Classroom:
def __init__(self, name, supervisor, students, grades):
self.name = name
self.supervisor = supervisor
self.students = []
# do it here
for name, grade in zip(students, grades):
self.students.append(student(name, grade))
Also, using _ and __ for values you use is a pretty big red flag. Normally, _ is used as a signal to the developer that a value isn't used:
# we don't use the values produced by range, so
# the _ is a throwaway
five_students = [student('tom', 100) for _ in range(5)]
# now we use the value, so use a name for it
five_students = [student('tom', grade) for grade in range(95, 100)]
1 Comment
Student 2) Other way around with variable names/args/attributes, those should not start with capital letter 3) You don't have to differentiate variable names passed to the init and attributes name in such artificial way as adding snake case to the end, actually they can be the same
self.students = []; self.students.append(student(...))