【问题标题】:Can I avoid using exec() in this case?在这种情况下我可以避免使用 exec() 吗?
【发布时间】:2021-11-17 15:01:41
【问题描述】:

由于某些原因,我有一个类以下列方式继承另一个类 (例如)

    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[_])+")"

我想从“学生”类创建多个实例,但作为“课堂”类的一部分,即可以像 self.student 一样引用。

但我不知道输入的学生人数(可能很多),我想为每个学生创建一个对象,例如:

self.Student_Mark=student(mark,20)
self.Student_Peter=student(peter,15)
...

等等。

然后的问题是我想像上面那样做一个赋值语句,但是如果不使用 exec() 函数我不能这样做,我已经阅读了在生产级别使用 exec() 函数的安全危险,所以我怎样才能在这里用具有相同功能的东西替换 exec() ?

【问题讨论】:

  • 使用列表而不是 n 个变量。例如。 self.students = []; self.students.append(student(...))
  • 旁注:对我来说,您的代码很难阅读。去掉变量名后的下划线并在事物之间添加空格。见Style Guide for Python Code

标签: python exec


【解决方案1】:

我不知道你为什么要这样命名你的属性。但是你可以使用setattr。此外,我认为这不是一次性变量的好用例,而是您可以编写:

for ix, name in enumerate(self.List_of_Students_Grades):
    setattr(
        self, 
        f"Student_{name}", 
        student(name, self.List_of_Students_Grades[index])
    )

【讨论】:

  • 最好避免执行 exec,即使其他答案在建议完全不同的方法时是正确的。
【解决方案2】:

一个框架问题:为什么教室是学生的子类?教室就是一个房间,但更重要的是,一个教室(由于显而易见的原因,不能真正称之为class)代表一组学生、一个老师/主管和一个名字。所以创建一组学生,而不是为每个学生创建一个变量:

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))

此外,使用 ___ 作为您使用的值是一个很大的危险信号。通常,_ 用作向开发人员发出未使用值的信号:

# 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)]

【讨论】:

  • 添加到您对 OP 的回答中:1) 始终在 Python 中以大写字母开头类名,因此 Student 2) 以其他方式使用变量名/args/attributes,那些不应该开始用大写字母 3) 你不必区分传递给 init 的变量名和属性名,比如在末尾添加蛇形大小写,实际上它们可以是相同的
猜你喜欢
  • 2020-04-18
  • 1970-01-01
  • 2023-03-06
  • 1970-01-01
  • 2023-03-24
  • 1970-01-01
  • 2019-08-24
  • 2011-05-08
  • 1970-01-01
相关资源
最近更新 更多