1. 시나리오
| 단계 | 핵심 변화 | 학습 포인트 |
| 1. 딕셔너리 리스트 | 데이터 나열 | 데이터가 많아질수록 관리가 힘들고 실수가 잦아짐을 깨달음 |
2. 생성 함수 (create_student) | 구조화 시작 | 데이터의 형태(틀)를 일정하게 맞추는 법을 배움 |
| 3. 기능 함수 (총점, 평균, 표현) | 로직 분리 | 데이터와 그 데이터를 처리하는 함수가 서로 연관되어 있음을 인지 |
| 4. 클래스 선언 | 데이터 + 기능 결합 | 흩어져 있던 데이터와 함수를 하나의 ‘객체’로 묶는 캡슐화를 이해 |
2. 딕셔너리 리스트
# object_1_basic.py
students=[
{"name": "윤이성", "Korean": 87, "math":98, "english": 88, "science":99},
{"name": "연하진", "Korean": 88, "math":99, "english":88, "science": 100}
]
print("이름", "총점", "평균", sep='\t')
for student in students:
score_sum=student['Korean']+student['math']+student['english']+student['science']
score_average=score_sum/4
print(student['name'], score_sum, score_average, sep='\t')
# 키와 값을 깥이 써서 키 값을 계속 반복하는 문제점이 있다.
# students라는 학생들 객체가 있다는 것을 이해해야 한다.
-----------------------------
(.venv) robot@robot:~/Robot-AI$ /home/robot/Robot-AI/.venv/bin/python /home/robot/Robot-AI/Python/class/object_1_basic.py
이름 총점 평균
윤이성 372 93.0
연하진 375 93.75
3. 구조화 시작
# object_2_basic.py
def create_student(name, korean, math, english, science):
return(
{
"name" : name,
"Korean" : korean,
"math" : math,
"english" : english,
"science" : science
}
)
students=[
create_student("윤이성", 87, 98, 88, 99),
create_student("연하진", 88, 99, 88, 100)
]
print("이름", "총점", "평균", sep='\t')
for student in students:
score_sum=student['Korean']+student['math']+student['english']+student['science']
score_average=score_sum/4
print(student['name'], score_sum, score_average, sep='\t')
# 키와 값을 깥이 써서 키 값을 계속 반복하는 문제점이 있다.
# students라는 학생들 객체가 있다는 것을 이해해야 한다.
## 학생객체와 학생들 객체를 나눠서 생각하기 시작했다.
## 학생의 총점과 평균은 학생객체에 넣어서 생각해도 되지 않을까?
-----------------------------
(.venv) robot@robot:~/Robot-AI$ /home/robot/Robot-AI/.venv/bin/python /home/robot/Robot-AI/Python/class/object_2_basic.py
이름 총점 평균
윤이성 372 93.0
연하진 375 93.75
4. 기능별 분류
4.1 엉성한 기능별 함수
# object_3_basic.py
def create_student(name, korean, math, english, science):
return(
{
"name" : name,
"Korean" : korean,
"math" : math,
"english" : english,
"science" : science
}
)
def score_sum():
score_sum=student['Korean']+student['math']+student['english']+student['science']
return score_sum
def score_average():
score_average=score_sum()/4
return score_average
def print_score():
print(student['name'], score_sum(), score_average(), sep='\t')
students=[
create_student("윤이성", 87, 98, 88, 99),
create_student("연하진", 88, 99, 88, 100)
]
print("이름", "총점", "평균", sep='\t')
for student in students:
print_score()
# 키와 값을 깥이 써서 키 값을 계속 반복하는 문제점이 있다.
# students라는 학생들 객체가 있다는 것을 이해해야 한다.
## 학생객체와 학생들 객체를 나눠서 생각하기 시작했다.
### 학생의 총점과 평균을 학생객체에 넣어서 생각하려고 했다.
### 출력도 학생객체가 담당하려고 했다.
### student라는 전역변수에 의존하고 있다.
### 그래서 함수와 객체와의 연결성이 보장되지 않는다.
-----------------------------
(.venv) robot@robot:~/Robot-AI$ /home/robot/Robot-AI/.venv/bin/python /home/robot/Robot-AI/Python/class/object_3_basic.py
이름 총점 평균
윤이성 372 93.0
연하진 375 93.75
- 위 코드 문제점
- student라는 전역변수에 의존하고 있다.
- 그래서 함수와 객체와의 연결성이 보장되지 않는다.
4.2 덜 엉성한 기능별 함수
def create_student(name, korean, math, english, science):
return(
{
"name" : name,
"Korean" : korean,
"math" : math,
"english" : english,
"science" : science
}
)
def score_sum(student):
score_sum=student['Korean']+student['math']+student['english']+student['science']
return score_sum
def score_average(student):
score_average=score_sum(student)/4
return score_average
def print_score(student):
print(student['name'], score_sum(student), score_average(student), sep='\t')
students=[
create_student("윤이성", 87, 98, 88, 99),
create_student("연하진", 88, 99, 88, 100)
]
print("이름", "총점", "평균", sep='\t')
for student in students:
print_score(student)
# 키와 값을 깥이 써서 키 값을 계속 반복하는 문제점이 있다.
# students라는 학생들 객체가 있다는 것을 이해해야 한다.
## 학생객체와 학생들 객체를 나눠서 생각하기 시작했다.
### 학생의 총점과 평균을 학생객체에 넣어서 생각하려고 했다.
### 출력도 학생객체가 담당하려고 했다.
### student라는 전역변수에 의존하고 있다.
### 그래서 함수와 객체와의 연결성이 보장되지 않는다.
#### 함수의 매개변수로 student 객체를 넣어서 연결했다.
#### 그런데 마지막 print_score의 리턴이 없다.
#### 출력 담당은 외부에서 처리하는 것일 좋다. 출력을 파일로도 웹으로도 보내야 하기 때문.
-----------------------------
(.venv) robot@robot:~/Robot-AI$ /home/robot/Robot-AI/.venv/bin/python /home/robot/Robot-AI/Python/class/object_4_basic.py
이름 총점 평균
윤이성 372 93.0
연하진 375 93.75
4.3 개선된 기능별 함수
def create_student(name, korean, math, english, science):
return(
{
"name" : name,
"Korean" : korean,
"math" : math,
"english" : english,
"science" : science
}
)
def score_sum(student):
score_sum=student['Korean']+student['math']+student['english']+student['science']
return score_sum
def score_average(student):
score_average=score_sum(student)/4
return score_average
def student_info(student):
return(f"{student['name']}\t{score_sum(student)}\t{score_average(student)}\t")
students=[
create_student("윤이성", 87, 98, 88, 99),
create_student("연하진", 88, 99, 88, 100)
]
print("이름", "총점", "평균", sep='\t')
for student in students:
print(student_info(student))
# 키와 값을 깥이 써서 키 값을 계속 반복하는 문제점이 있다.
# students라는 학생들 객체가 있다는 것을 이해해야 한다.
## 학생객체와 학생들 객체를 나눠서 생각하기 시작했다.
## 학생의 총점과 평균을 학생객체에 넣어서 생각하려고 했다.
### 출력도 학생객체가 담당하려고 했다.
### student라는 전역변수에 의존하고 있다.
### 그래서 함수와 객체와의 연결성이 보장되지 않는다.
#### 함수의 매개변수로 student 객체를 넣어서 연결했다.
#### 그런데 마지막 print_score의 리턴이 없다.
#### 출력 담당은 외부에서 처리하는 것일 좋다. 출력을 파일로도 웹으로도 보내야 하기 때문.
##### 모든 것이 개선된 코드이다.
-----------------------------
(.venv) robot@robot:~/Robot-AI$ /home/robot/Robot-AI/.venv/bin/python /home/robot/Robot-AI/Python/class/object_5_basic.py
이름 총점 평균
윤이성 372 93.0
연하진 375 93.75
5. 클래스
지금까지의 과정을 요약하자면,
- 딕셔너리의 키를 계속 반복해서 집어 넣는것에서 해방. create_student()
- 기능별로 함수를 만들어서 코드 재사용. 단 전역변수 의존성 문제가 있음.
- 전역변수 의존성 문제를 매개 변수를 이용해서 해결.
- print_info 함수가 리턴 함수가 되도록 해서, 계산과 출력을 분리함.
- 그래서 최종, 각 기능별 함수를 매개변수를 이용해서 student 오브젝트와 연결되도록 함.
그런데, 각 기능별 함수를 보면, 이건 student라는 영역, 패밀리에 묶을 수 있다. 이러면 번거롭게 student라는 매개변수로 묶지 않아도 되지 않을까? 이런 생각이 클래스에 녹아있다.
즉, 아래와 같은 합의에 도착할 수 있다.
- 내가 학생이라는 객체를 만들어 내는 형태(변수와 함수들)를 모두 가지고 있다.
- 학생(student)이라는 객체를 만들 때, 나라는 클래스를 통해서 만들면 내 모든 변수와 함수들을 사용할 수 있게된다.
- 그래 그럼 나라는 클래스 이름은 Student라고 하고 자료형은 class라고 하자.
class Student - 그러면 student object는 Student라는 객체가 생성해서 주는것으로 하고
student=Student()로 하자.
이런 합의의 결과가 아래의 코드다.
# class_exterior.py
class Student:
pass
student=Student() # 객체를 만들었다. 인스턴스라고 한다.
studnts=[ # 인스턴스 2 개를 만들어서 students 리스트에 넣었다.
Student(),
Student()
]
외형을 저렇게 만들어 놓았으니 이제 안쪽 인테리어를 마감할 차례다.
- 내가 만든 객체는 모두 이 범위(class)내에서는 self다. 이제 student를 매개변수로 쓰지 않고 self로 연결된다.
- 객체를 만들어주는 함수를 만들자. 생성자. def __init__(self, arg*): 함수로 만든다.
- 객체를 삭제하는 함수도 있다. 소멸자. def __del__(self):
- 이 객체 내에 선언되는 변수는 self.variables로 연결된다.
- 이 객체 내에서 선언되는 함수(메소드) 모드 function(self, arg*) 형태로 구성된다.
그러므로 아래처럼 class 정의부를 선언할 수 있다.
# class_interor.py
class Student:
def __init__(self, name, korean, math, english, science): #생성자
self.name=name
self.Korean=korean
self.math=math
self.english=english
self.science=science
def score_sum(self):
return self.Korean+self.math+self.english+self.science
def score_average(self):
return self.score_sum()/4
def student_info(self):
return f"{self.name}\t{self.score_sum()}\t{self.score_average()}"
class 내부에서 정의되는 함수가 다른 내부 함수를 콜 할 때는 self.funciton(self)로 호출하면 안되는 것만 주의하면 쉽게 위와 같은 형태를 만들 수 있을 것이다.
아래는 최종 class 파일이다.
# classs_student.py
class Student:
def __init__(self, name, korean, math, english, science): #생성자
self.name=name
self.Korean=korean
self.math=math
self.english=english
self.science=science
def score_sum(self):
return self.Korean+self.math+self.english+self.science
def score_average(self):
return self.score_sum()/4
def student_info(self):
return f"{self.name}\t{self.score_sum()}\t{self.score_average()}"
students = [
Student("윤이성", 87, 98, 88, 99),
Student("연하진", 88, 99, 88, 100)
]
for student in students:
print(student.student_info())
-----------------------------
(.venv) robot@robot:~/Robot-AI$ /home/robot/Robot-AI/.venv/bin/python /home/robot/Robot-AI/Python/class/class_student.py
윤이성 372 93.0
연하진 375 93.75