Python/파이선과 친해지기

[Python] - Python과 친해지기-학생관리 프로그램ver2

우리는 저번 학생 관리 프로그램을 만들 때 보다 문자열을 보다 세부적으로 다룰 수 있게 되었고, 정의된 모듈을 가지고 올 수 있게 되었으며, 사용자와 상호작용할 수 있는 방법을 알았으고 이를 파일로 입력 / 출력할 수 있는 방법을 알았다. (WOW 이렇게나 발전하다니, 오늘 저녁은 치킨이닭)

 

이제 이러한 새로 배운 지식으로 우리의 학생관리 프로그램을 다음의 조건들에 맞게 한 단계 진화시켜보자

 

추가된 개발조건

① 같은 폴더에 new_student.txt를 생성하고 그곳에서 학생정보를 가져와서 입력받는 기능을 추가할 것
② 통과한 학생에 대해서만 콘솔로 성적 정보를 입력받는 기능을 추가할 것

③ 모든 학생정보를 출력할 수 있는 기능을 students로 출력할 수 있게 기존 기능을 개선할 것
④ 파라미터는 students만 받아 랜덤 한 학생의 정보를 출력하는 기능을 추가할것(random 모듈의 randrange함수를 사용할 것)

 

* new_student.txt는 [학생 번호] [학생 이름]이 여러 줄로 구성된 파일이다.
* 이제 입출력을 배웠으니, students는 초기화 하자

 

우선 자신이 코딩할 수 있는 부분을 코딩해보고 아래의 필자의 코드를 참고하도록 하자(아직도 우리는 최상의 코드를 만들 수 없다 ㅠㅠ)


학생관리 프로그램 ver1보다는 훨씬 쉬워 보인다. 처음 조건부터 개발 착수해보자

① 같은 폴더에 new_student.txt를 생성하고 그곳에서 학생정보를 가져와서 입력받는 기능을 추가할 것

예시로 다음과 같은 new_students.txt를 생성하자

P_01 CHEELL
R_03 GLAADOS
T_04 SOMEONE

①은 다음과 같이 구현하면 될 것 같다.

students = dict()
## 새마음 새출발 새Dictionary

def add_students_file(target_dict) :
    with open("new_students.txt","r") as f:
        data = f.readlines()
        for i in range(len(data)) :
            temp_data = data[i].strip()
            student_num = temp_data.split()[0]
            student_name = temp_data.split()[1]
            target_dict[(student_num,student_name)] = list()
    with open("new_students.txt","w") as f :
        f.write("")

코드를 해석해보자. 저번과 비슷한 느낌으로 target_dict은 함수 내부에서 수정이 가능하니 파라미터로 받아왔고, with open("new_students.txt","r") as f를 통해서 파일 핸들을 읽기 모드로 열었다. 그 후 data에 f.readlines()로 나온 리스트를 저장했고, (현재 data = ["P_01 CHEELL", "R_03 GLAADOS"]) for문을 통해 data의 공백을 strip() 함수로 제거해 준후, 공백을 기준으로 나누어 이를 튜플로 target_dict;의 key로 삼아 list로 value를 초기화했다. 추가로 받아온 내용은 지우기 위해 다시 한번 f를 덮어쓰기 모드("w")로 열어 빈 값을 넣어주었다.

 

② 통과한 학생에 대해서만 콘솔로 성적 정보를 입력받는 기능을 추가할 것

②는 다음과 같이 구현할 수 있다.

def add_scores(target_dict) :
    keys = list(target_dict.keys())
    values = list(target_dict.values())
    stop = [False for i in range(len(keys))]

    for i in range(len(stop)) :
        if(len(value[i]) == 0 ):
            continue
        else :
            if(value[i][-1] <= 70) :
                stop[i] = True

    for i in range(len(keys)) :
        if(stop[i] == False) :
            score = int(input(keys[i][1]+"의 성적은? : "))
            value[i].append(score)

우선 target_dict의 key와 value를 list화 해서 각각 keys와 values에 저장하였다. 또한 저번처럼 stop을 만들어 응시한 마지막 시험이 70 이하인 학생들에 대해서는 입력을 받지 않도록 하였다. 중간 for문의 if(len(value[i]) ==0)는 맨 처음 응시하는 경우 value [해당 학생의 인덱스][-1]을 하면 배열의 길이가 0이라 마지막을 찾을 수 없어 에러가 발생하기 때문에 continue를 지시하였다. 그 후 stop[i]값이 False인 학생들을 int(input(score = int(input(keys[i][1]+"의 성적은? : "))을 하여 응시결과를 입력받았다.

* stop을 생성한 stop = [False for i in range(len(keys))] 은 Python의 고급 기능인 내포(Comprehension)인데, 조만간 볼 것이다.(아니 미 X놈아 그러면 지금 어떻게 하라고!)

 

③ 모든 학생정보를 출력할 수 있는 기능을 students.txt로 출력할 수 있게 기존 기능을 개선할 것

③은 다음과 같이 구현할 수 있다.

def show_students(target_dict,show_type) :
    keys = list(target_dict.keys())
    values = list(target_dict.values())
    if(show_type == 1) :
        for i in range(len(target_dict)) :
            print("학생번호 "+keys[i][0]+": "+keys[i][1])
    elif(show_type == 2) :
        with open("student.txt","w") as f:
            for i in range(len(target_dict)) :
                f.write("학생번호 "+keys[i][0]+": "+keys[i][1]+"\n")

ver1에서 만들었던 show_students함수를 개량했다. 콘솔로 출력할지(show_type : 1), 파일로 출력할지(show_type : 2)를 지정하였고, show_type에 따라 출력을 달리하였다. 파일로 출력할 땐 마지막에 개행을 함으로 가독성을 높였다.(write() 함수는 end="\n"뭐 이런 파라미터가 없다. print와 다르게 개행을 명시적으로 해주어야 된다.)

 

④ 파라미터는 students만 받아 랜덤한 학생의 정보를 출력하는 기능을 추가할 것(random 모듈의 randrange함수를 사용할 것)

마지막 조건인 ④는 일단 random이라는 모듈을 불러오고 randrange()의 사용을 보아야 한다. randrange()는 2개의 정수 파라미터를 받아 그 사이의 값(인덱스처럼 계산된다. randrange(0,10)이면 0~9중 하나 반환)을 랜덤으로 반환하는 함수이다. 다음과 같이 구현할 수 있다.

import random

def rshow_students(target_dict) :
    limit = len(target_dict)
    keys = list(target_dict.keys())
    o_index = random.randrange(0,limit)
    print("학생번호 "+keys[o_index][0]+": "+keys[o_index][1])

우선 random 모듈을 import 했다. 함수 내부에서는 randrange의 사용을 위해서 범위를 설정할 limit정수를 len(target_dict)으로 초기화했고, 출력했다.

 

이제 우리 학생관리 프로그램의 전체 코드는 다음과 같다.

import random

students = dict()

def add_students(target_dict, stu_num, stu_name) :
    target_dict[(stu_num, stu_name)] = list()

    
def show_students(target_dict,show_type) :
    keys = list(target_dict.keys())
    values = list(target_dict.values())
    if(show_type == 1) :
        for i in range(len(target_dict)) :
            print("학생번호 "+keys[i][0]+": "+keys[i][1])
    elif(show_type == 2) :
        with open("student.txt","w") as f:
            for i in range(len(target_dict)) :
                f.write("학생번호 "+keys[i][0]+": "+keys[i][1]+"\n")

def rshow_students(target_dict) :
    limit = len(target_dict)
    keys = list(target_dict.keys())
    o_index = random.randrange(0,limit)
    print("학생번호 "+keys[o_index][0]+": "+keys[o_index][1])
    
                

def add_score(target_dict, score_list) :
    keys = list(target_dict.keys())
    values = list(target_dict.values())
    stop = [False,False,False,False,False]

    for i in range(4) :
        add = True
        for j in range(len(values)) :
            if(stop[j] == True) :
                continue
            else :
                values[j].append(score_list[i][j])
                if(values[j][-1] <= 70) :
                    stop[j] = True
                    
def add_students_file(target_dict) :
    with open("new_students.txt","r") as f:
        data = f.readlines()
        for i in range(len(data)) :
            temp_data = data[i].strip()
            student_num = temp_data.split()[0]
            student_name = temp_data.split()[1]
            target_dict[(student_num,student_name)] = list()
    with open("new_students.txt","w") as f :
        f.write("")

def add_scores(target_dict) :
    keys = list(target_dict.keys())
    values = list(target_dict.values())
    stop = [False for i in range(len(keys))]
    print(keys,stop)

    for i in range(len(stop)) :
        if(len(values[i]) == 0 ):
            continue
        else :
            if(values[i][-1] <= 70) :
                stop[i] = True

    for i in range(len(keys)) :
        if(stop[i] == False) :
            score = int(input(keys[i][1]+"의 성적은? : "))
            values[i].append(score)
    

뿌듯한 마음이 들지 않는가? 이번 시간이 완벽하게 이해가 되었다면 어디 가서 이제 제가 Python좀 씁니다라고 자랑해도 된다. 이번 시간까지 해서 길다면 길고 짧다면 짧았던 Python과 친해지기가 끝이 났다. 아직 얼굴만 좀 아는 사이이고, 조금 더 깊은 관계를 맺기 위해서는 가야 할 길이 태산처럼 많이 남아있다. 학습을 할 때 조바심을 내는 것은 정말 좋지 않다. 빠르게 흥미가 떨어지고, 두 번 다시 안 보게 되는 것만큼 학습을 좀먹는 것도 드물다고 생각한다. 이제 필자는 Python과 "매우"친해지기 포스팅의 클래스와 객채를 준비하여 다시 한번 여러분들의 Python의 세계의 길잡이를 역할을 하겠다.