Python 클래스와 상속
이 토픽을 마치면
클래스가 무엇인지, 왜 필요한지 이해하고, 클래스를 정의하여 객체를 만들고, 상속으로 코드를 재사용하는 방법을 알게 됩니다.
클래스가 필요한 순간
학생 데이터를 관리한다고 합시다. 딕셔너리로도 됩니다.
python
student1 = {"name": "김훈", "score": 90}student2 = {"name": "이수", "score": 85}
def get_grade(student): if student["score"] >= 90: return "A" elif student["score"] >= 80: return "B" return "C"문제는 규모가 커질 때입니다. 학생에게 "출석 체크", "점수 수정", "과목 추가" 같은 기능이 붙으면, 함수가 흩어져서 "학생 관련 코드가 어디에 있지?"를 매번 찾아야 합니다.
클래스는 데이터(속성)와 기능(메서드)을 하나로 묶습니다.
클래스 정의와 인스턴스 생성
python
class Student: def __init__(self, name, score): self.name = name # 인스턴스 속성 self.score = score def grade(self): if self.score >= 90: return "A" elif self.score >= 80: return "B" return "C" def introduce(self): return f"{self.name} ({self.grade()}등급)"python
# 인스턴스 생성s1 = Student("김훈", 90)s2 = Student("이수", 85)
print(s1.introduce()) # 김훈 (A등급)print(s2.grade()) # Bs2.score = 92 # 점수 수정print(s2.grade()) # A__init__은 생성자 — 인스턴스가 만들어질 때 자동 호출됩니다self는 자기 자신 — 이 인스턴스의 속성에 접근하는 통로입니다Student("김훈", 90)이 호출되면__init__(self, "김훈", 90)이 실행됩니다
왜 클래스를 쓰는가
같은 기능을 함수와 딕셔너리로도 구현할 수 있습니다. 클래스의 진짜 가치는 "이 데이터로 할 수 있는 것"을 한 곳에 모은다는 점입니다.
python
# 함수 방식 — 데이터와 기능이 분리student = {"name": "김훈", "scores": []}add_score(student, 90)get_average(student)get_grade(student)
# 클래스 방식 — 데이터와 기능이 하나student = Student("김훈")student.add_score(90)student.average()student.grade()student.을 타이핑하면 IDE가 "이 객체로 할 수 있는 것" 목록을 보여줍니다. 코드 자체가 문서 역할을 합니다.
상속 — 공통 코드를 물려받기
"학생"과 "교수" 모두 "이름"과 "소속"이 있습니다. 공통 부분을 부모 클래스에 넣고, 차이점만 자식 클래스에서 추가합니다.
python
class Person: def __init__(self, name, department): self.name = name self.department = department def introduce(self): return f"{self.name} ({self.department})"
class Student(Person): def __init__(self, name, department, student_id): super().__init__(name, department) # 부모 생성자 호출 self.student_id = student_id def introduce(self): return f"학생 {self.name} ({self.student_id})"
class Professor(Person): def __init__(self, name, department, lab): super().__init__(name, department) self.lab = lab def introduce(self): return f"교수 {self.name} ({self.lab} 연구실)"python
s = Student("김훈", "생명과학", "2024-001")p = Professor("박진", "생명과학", "유전체학")
print(s.introduce()) # 학생 김훈 (2024-001)print(p.introduce()) # 교수 박진 (유전체학 연구실)print(s.department) # 생명과학 — Person에서 상속받은 속성super().__init__()으로 부모의 생성자를 호출합니다- 자식 클래스에서 같은 이름의 메서드를 정의하면 오버라이드(재정의) 됩니다
department는Person에 정의했지만,Student와Professor모두 사용할 수 있습니다
핵심 정리
| 개념 | 의미 |
|---|---|
| 클래스 | 데이터(속성) + 기능(메서드)을 묶는 설계도 |
| 인스턴스 | 설계도로 만든 실제 객체 (s1 = Student(...)) |
__init__ | 생성자 — 인스턴스 만들 때 자동 실행 |
self | 현재 인스턴스 자신을 가리킴 |
| 상속 | 부모 클래스의 속성/메서드를 자식이 물려받음 |
super() | 부모 클래스의 메서드를 호출 |
| 오버라이드 | 자식이 부모의 메서드를 재정의 |
클래스를 "반드시 써야 하는" 규칙은 없습니다. 작은 스크립트에서는 함수와 딕셔너리로 충분합니다. 하지만 코드가 커지고, 같은 구조의 데이터를 여러 개 다뤄야 할 때, 클래스는 코드를 정리하는 가장 검증된 도구입니다.