from datetime import date, datetime from typing import Optional, Union class Student: """学生实体类,包含学生的基本信息和相关属性""" def __init__(self, name: str, # 姓名,非空字符串 id_card: str, # 身份证号, 唯一标识学生,非空字符串 stu_id: str, # 学号, 唯一标识学生,非空字符串 gender: Optional[bool] = None, # 性别,True为男,False为女 height: Optional[int] = None, # 身高, 单位为cm weight: Optional[float] = None, # 体重, 单位为kg,小数点后一位 enrollment_date: Optional[Union[date, str]] = None, # 入学日期 class_name: Optional[str] = None, # 班级名称 major: Optional[str] = None, # 专业名称 email: Optional[str] = None, # 电子邮箱 phone: Optional[str] = None # 联系电话 ): # 基本信息 self.name = name self.id_card = id_card self.stu_id = stu_id self.gender = gender self.height = height self.weight = weight self.enrollment_date = enrollment_date self.class_name = class_name self.major = major self.email = email self.phone = phone # 从身份证号码派生的属性 self._age = None self._birthday = None self._parse_id_card() def _parse_id_card(self): """从身份证号码中提取出生日期和计算年龄""" if not self.id_card or len(self.id_card) != 18: return try: # 提取出生日期 birth_date_str = self.id_card[6:14] self._birthday = datetime.strptime(birth_date_str, '%Y%m%d').date() # 计算年龄 today = date.today() self._age = today.year - self._birthday.year - ( (today.month, today.day) < (self._birthday.month, self._birthday.day)) # 从身份证第17位判断性别 if self.gender is None: gender_digit = int(self.id_card[16]) self.gender = gender_digit % 2 == 1 # 奇数为男,偶数为女 except ValueError: # 身份证号码格式错误 pass @property def age(self) -> int: """获取计算得到的年龄""" return self._age @property def birthday(self) -> date: """获取从身份证提取的出生日期""" return self._birthday def to_dict(self) -> dict: """将学生对象转换为字典格式""" return { 'name': self.name, 'id_card': self.id_card, 'stu_id': self.stu_id, 'gender': self.gender, 'height': self.height, 'weight': self.weight, 'enrollment_date': str(self.enrollment_date) if self.enrollment_date else None, 'class_name': self.class_name, 'major': self.major, 'email': self.email, 'phone': self.phone, 'age': self.age, 'birthday': str(self.birthday) if self.birthday else None }