用Python列表存储类实例?

21 投票
3 回答
120537 浏览
提问于 2025-04-16 02:47

假设我们有一个Python类叫做 class Student():,还有一个空的列表 names = []。接下来,我想创建几个 Student() 的实例,并把它们放到这个列表 names 里。

names = [] # For storing the student instances
class Student():
    def __init__(self, score, gender):
        self.score = score
        self.gender = gender

现在我想查看所有男学生的分数,我可以这样做吗?

scores = []
for i in names:
    if i.gender ==  "Male":
        scores.append(i.score)

我的问题是:如何创建一个列表,能够存储 Student 的实例?换句话说,当我写 names = [] 时,怎么能说明这个列表里的每个元素都是 Student 的实例,这样我就可以使用这些元素的属性,尽管Python是弱类型的?我希望我说得够清楚;)

我可以这样写吗:

    for i in range(len(names)):
        student = Student()
        student = names[i]
        if student.gender == "Male":
            # Whatever

我想我不能...

3 个回答

6

我对面向对象编程(OOP)还比较陌生,但这个方法不是挺符合你想要的效果吗?name_list 是一个类变量,每次你创建一个新的 Student 对象时,它都会被添加到 Student.name_list 里。比如说,如果你有一个方法 cheat(self),想要在第三个学生身上执行这个方法,你可以这样运行:Student.name_list[2].cheat()。代码如下:

class Student():
    name_list = []
    def __init__(self, score, gender):
        Student.name_list.append(self)
        self.score = score
        self.gender = gender

    #this is just for output formatting
    def __str__(self):
        return "Score: {} || Gender: {}".format(self.score, self.gender)

#again for output formatting
def update(): print([str(student) for student in Student.name_list])

update()
Student(42, "female")
update()
Student(23, "male")
update()
Student(63, "male")
Student(763, "female")
Student("over 9000", "neutral")
update()

输出:

[]
['Score: 42 || Gender: female']
['Score: 42 || Gender: female', 'Score: 23 || Gender: male']
['Score: 42 || Gender: female', 'Score: 23 || Gender: male', 'Score: 63 || Gender: male', 'Score: 763 || Gender: female', 'Score: over 9000 || Gender: neutral']
7

首先,Python 并不是 弱类型语言。不过,它是动态类型的,这意味着你不能为你的列表指定元素的类型。

不过,这并不妨碍你访问对象的属性。这样做是完全可以的:

names = [Student(1,"Male"), Student(2,"Female")]
scores = []
for i in names:
    if i.gender ==  "Male":
        scores.append(i.score)

不过,用列表推导式来写会更符合Python的风格:

names = [Student(1,"Male"), Student(2,"Female")]
scores = [i.score for i in names if i.gender == "Male"]
18

你试过上面的代码吗?应该是可以正常工作的。你可以把它简化成:

scores = [ student.name for student in names if student.gender == "Male" ]

注意,叫这个列表为 names 其实有点误导,因为它实际上是一个 Student 实例的列表。

你不能把这个列表定义成只包含 Student 实例的列表,这不是 Python 的工作方式。

你是在问怎么创建你叫做 names 的列表吗?

names = [ ]
for ( score, gender ) in <some-data-source>:
    names.append( Student( score, gender ) )

这当然是等价于

names = [ Student( score, gender ) for score, gender in <some-data-source> ]

而且又等价于

names = [ Student( *row ) for row in <some-data-source> ]

如果你需要对每一行进行很多处理,你可以把处理的部分放到一个单独的函数里,或者使用 for 循环。

def process_row( row ):
    ...
    return score, gender

names = [ Student( *process_row( row ) ) for row in <some-data-source> ]

回应你的编辑,我觉得你是在尝试在 Python 中声明变量的类型。你写了:

for i in range(len(names)):
    student = Student()
    student = names[i]
    if student.gender == "Male":
        # Whatever

那行 student = Student() 的目的是什么?你是在尝试声明变量 student 的类型吗?别这么做。下面的代码可以实现你想要的:

for student in students:
   if student.gender == "Male":
       # Whatever

注意几点:

  1. 我们不需要遍历 range(n) 然后去查找每个实例在 names 中;遍历一个容器的每个元素正是 for 循环的目的。
  2. 你不需要对 student 的类型做任何声明——它可以是字符串、布尔值、列表、Student,或者其他任何东西。这就是 动态类型。同样,students 不一定要是一个列表;你可以遍历任何 可迭代对象
  3. 当你写 student.gender 时,Python 会获取 studentgender 属性,如果没有这个属性,它会抛出一个异常。

撰写回答