用Python列表存储类实例?
假设我们有一个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 个回答
我对面向对象编程(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']
首先,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"]
你试过上面的代码吗?应该是可以正常工作的。你可以把它简化成:
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
注意几点:
- 我们不需要遍历
range(n)
然后去查找每个实例在names
中;遍历一个容器的每个元素正是for
循环的目的。 - 你不需要对
student
的类型做任何声明——它可以是字符串、布尔值、列表、Student
,或者其他任何东西。这就是 动态类型。同样,students
不一定要是一个列表;你可以遍历任何 可迭代对象。 - 当你写
student.gender
时,Python 会获取student
的gender
属性,如果没有这个属性,它会抛出一个异常。