Список 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 = []
, как я могу утверждать, что каждый элемент в names
является экземпляром Student
, чтобы я мог использовать атрибуты этого элемента, несмотря на то, что python является слабым типом? Надеюсь, я ясно дал понять;)
Могу ли я написать как
for i in range(len(names)):
student = Student()
student = names[i]
if student.gender == "Male":
# Whatever
Я думаю, нет...
Ответы
Ответ 1
Вы пробовали свой код выше? Это должно работать нормально. Вы можете сжать это в:
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 получит атрибут gender
для student
или вызовет исключение, если у него его нет.
Ответ 2
Прежде всего, Python не является слабо типизированным. Однако он динамически типизирован, поэтому вы не можете указать тип элемента для своего списка.
Однако это не мешает вам получить доступ к атрибутам объекта. Это работает просто отлично:
names = [Student(1,"Male"), Student(2,"Female")]
scores = []
for i in names:
if i.gender == "Male":
scores.append(i.score)
Тем не менее, более питонно писать это, используя понимание списка:
names = [Student(1,"Male"), Student(2,"Female")]
scores = [i.score for i in names if i.gender == "Male"]
Ответ 3
Я новичок в ООП, но разве это не делает то, что вы хотите, довольно приятно? 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']