1. Студент не должен наследовать группу. Наследование не про это.
Вы можете представить группу просто как массив студентов, как в вашем примере.
group1 = []
group.append(Student("ivan", "perov"))
group.append(Student("petr", "ivanov"))
Если у группы появится какая-то интересная логика, например согранение\загрузка, то можно завести для нее класс.
class Group:
def __init__(self):
self.students = []
def add_student(self, name, surname):
self.students.append(name, surname, self)
group = Group()
group.add_student("ivan", "perov")
group.add_student("petr", "ivanov")
Для доступа к студентам можно добавить функции геттеры, которые возвращают или весь массив или конкретных студентов по номеру или имени.
2. Сериализация и десериализация почти всегда требует монотонных действий. Не рекомендуется реализовывать ее самостоятельно. Для того же json есть встроенная библиотека. Для баз данных так же есть orm библиотеки(SQLAlchemy, Django ORM, peewee).
В python есть pickle которая умеет самостоятельно сохранять и загружать объекты в свой формат. Но она относительно медленная и опасная.