파이썬

0706 Class

인뽕 2026. 7. 8. 23:28

 

Class

 

-  객체지향 프로그래밍의 핵심 문법으로 비슷한 속성(데이터)과 기능(함수)을 하나로 묶어서, 새로운 자료형(틀)을 만드는 것 이다.

클래스로 생성한 객체들을 인스턴스라고 한다. 흔한 비유로 클래스를 정의하는 것은 붕어빵을 만들 때 사용하는 기본 틀을 제작하는 것에 해당하고, 인스턴스는 붕어빵 틀에 반죽을 넣어서 만들어진 붕어빵에 해당한다.

C++, 자바(Java), C# 같은 프로그래밍 언어는 기본적으로 클래스를 지원한다.


예를 들어 클래스를 통해 명함이라는 객체를 만들어 두면 명함 객체가 정수, 실수, 문자열과 마찬가지로 하나의 타입으로 인식되기 때문에 여러 명의 명함 정보도 쉽게 관리할 수 있다.

 

 

코드를 설계할 때, 멤버 변수와 멤버 함수는 생각하지 못했지만 클래스만 명시 해두고 싶을때, pass라는 키워드를 사용해 클래스 내부에 아무것도 넣지 않은 상태로 클래스를 정의할 수 있다.

 

 

파이썬에서 정의된 클래스를 이용해 인스턴스를 생성하려면 다음과 같이 클래스 이름 뒤에 ()를 넣으면 된다. 어떻게 보면 인스턴스를 생성하는 과정은 함수를 호출하는 것과 비슷다. 다음 코드가 실행되면 그림과 같이 'BusinessCard'라는 클래스의 인스턴스가 메모리의 0x0302ABB0 위치에 생성되고 card1이라는 변수가 이를 바인딩하게 된다.

 


파이썬 클래스에서 내부함수의 첫번째로 self라는 변수사용한다. self는 해당 클래스로 생성된 인스턴스 자기자신을 의미하고 이를 인스턴스 변수라고 부른다. 실제로 함수를 호출할때에는 따로 인자를 전달 할 필요는 없다.

 

위 그림에서 내부함수 set_info로 내부 변수 name, emain, addr을 정의하게 된다.

파이썬에서는 따로 변수의 자료형을 선언하지 않는다.

 

파이썬에서의 클래스 생성자는 __init__이라는이름을 갖는다. __init__이라는 함수를통해 생성과 동시에 내부변수를 초기화 할 수 있다. (소멸자는 __del__(self))

 

 

클래스의 상속은 다음과 같이 인자에 부모클래스의 이름을 넣어주면 된다.


 

실습

 

1.

 

생성자와 자신의 멤버변수 데이터를 출력하는 print_info라는 멤버함수를 가진 Contact라는 연락처 클래스를 만들고

Contact_list에서 연락처들을 연락처 입력, 출력, 삭제, 저장하며 관리하는 프로그램을 작성했다.

# -*- coding: utf-8 -*-
"""
Created on Mon Jul  6 09:19:01 2026

@author: ihhan


선택메뉴
1. 연락처 입력
2. 연락처 출력
3. 연락처 삭제(이름기준)
4. 종료: txt파일로 저장

"""
class Contact:
    def __init__(self,name,phone_number, e_mail, addr):
        self.name=name
        self.phone_number=phone_number
        self.e_mail=e_mail
        self.addr=addr
        
    def print_info(self):
        print('=========================')
        print('이름:',self.name)
        print('전화:',self.phone_number)
        print('메일:',self.e_mail)
        print('주소:',self.addr)
        print('=========================')



#--1. 연락처 입력 ----------------------------------
def set_contact():
    name=input('이름 입력:')
    phone_number=input('전화번호 입력:')
    e_mail=input('메일 입력:')
    addr=input('주소 입력:')
    return Contact(name,phone_number,e_mail,addr)
    
    
#--2. 연락처 출력 ----------------------------------
# contact 객체가 가지고 있는 값(변수)을 출력 :2.
def print_contact(contact_list):
    for contact in contact_list:
        contact.print_info();
        
        
#--3. 연락처 삭제 ----------------------------------
# 이름을 통해 삭제 :3.

def delete_contact(contact_list,name):
    for i, contact in enumerate(contact_list):
        if contact.name ==name:
            del contact_list[i]
            
            
#--4. 연락처 저장 ----------------------------------
# 종료 선택시, 파일로 저장
def store_contact(contact_list):
    f=open('db.txt','wt')
    for contact in contact_list:
        f.write(contact.name+'\n')
        f.write(contact.phone_number+'\n')
        f.write(contact.e_mail+'\n')
        f.write(contact.addr+'\n')
    f.close()
#--사용자 선택 메뉴--------------------------------
def print_menu():
    print('1. 연락처 입력')
    print('2. 연락처 출력')
    print('3. 연락처 삭제')
    print('4. 연락처 저장')
    menu=input('메뉴 선택: ')
    return int(menu)

def run():
    
    contact_list = []
    while 1:
        menu=print_menu()
        if menu==1:
            contact = set_contact()
            contact_list.append(contact)
        elif menu==2:
            print_contact(contact_list)
        elif menu==3:
            name = input('삭제할 이름 입력: ')
            delete_contact((contact_list), name)
        elif menu==4:
            store_contact(contact_list)
            break
        else:
            print('잘못된 명령입니다.')
        
if __name__=='__main__':# 파일 자체 실행 여부 확인
     run()

 

2.

 

member.csv 파일을 읽어와서 이름, 등급, 최근방문일 데이터를 갖고 있는 Member 인스턴스에 저장해 member_list를 만든다.\

 

class Member:
    def __init__(self,name,rate,DateofLastVisit,NumberofVisit):#이름,멤버 등급,최종방문일,방문수
        self.name=name
        self.rate=rate
        self.DateofLastVisit=DateofLastVisit
        self.NumberofVisit=NumberofVisit
    def print_info(self):
        print('=========================')
        print('이름:',self.name)
        print('등급:',self.rate)
        print('최근방문일:',self.DateofLastVisit)
        print('=========================')
        
with open('member.csv', 'r', encoding='utf-8') as f:
    lines = f.readlines()
    member_list = []
    
    
    for line in lines[1:]:              # [1:] → 첫 줄(헤더)은 건너뜀
        line = line.strip()               # 줄바꿈 문자 제거
        if not line:                    # 빈 줄이면 건너뜀
            continue
        values = line.split(',')        # 쉼표 기준으로 쪼개서 리스트로 만듦
        m = Member(values[0], values[1], values[3], values[4])
        if int(m.NumberofVisit) >= 50:
            member_list.append(m)

# 결과 출력
    for m in member_list:
        m.print_info()

 

 

3.

 

 

11만개의 병원 예약 정보가 담긴 엑셀 파일을 읽어와서, 진료일에 노쇼하는 환자들의 특징을 분석한다.

나는 실습 1번처럼 사용자가 직접 성별, 예약 대기기간, 연령대 별로 교차분석을 할 수 있는 프로그램을 만들었다.

 

# -*- coding: utf-8 -*-
"""
Created on Mon Jul  6 15:54:00 2026

@author: ihhan
"""
from datetime import datetime
class Patient:
    def __init__(self,PatientId,AppointmentId,Gender,ScheduledDay,AppointmentDay,Age,Neighbourhood,SMS_received,No_show):
        self.PatientId=PatientId
        self.AppointmentId=AppointmentId
        self.Gender=Gender
        self.ScheduledDay=ScheduledDay
        self.AppointmentDay=AppointmentDay
        self.Age=Age
        self.Neighbourhood=Neighbourhood
        self.SMS_received=SMS_received
        self.No_show=No_show
    def print_info(self):
        print('=========================')
        print('환자ID:',self.PatientId)
        print('예약ID:',self.AppointmentId)
        print('성별:',self.Gender)
        print('예약일:',self.ScheduledDay)
        print('진료예정일:',self.AppointmentDay)
        print('나이:',self.Age)
        print('지역:',self.Neighbourhood)
        print('SMS수신동의:',self.SMS_received)
        print('노쇼여부:',self.No_show)
        print('=========================')
#함수화 하려면 특정 (표본/전체) 두개의 데이터를 반환하는게 좋을듯

with open('medical.csv', 'r', encoding='utf-8') as f:
    lines = f.readlines()
    patient_list = []
       
    for line in lines[1:]:              # [1:] → 첫 줄(헤더)은 건너뜀
        line = line.strip()               # 줄바꿈 문자 제거
        if not line:                    # 빈 줄이면 건너뜀
            continue
        values = line.split(',')        # 쉼표 기준으로 쪼개서 리스트로 만듦
        p = Patient(values[0], values[1], values[2], values[3], values[4], values[5], values[6], values[7], values[8])
        patient_list.append(p)
        
                
    #연령별 노쇼율
    age_total = {
        "0~19세": 0,
        "20~39세": 0,
        "40~59세": 0,
        "60세 이상": 0
        }   

    age_noshow = {
        "0~19세": 0,
        "20~39세": 0,
        "40~59세": 0,
        "60세 이상": 0
        }

    for p in patient_list:

        age = int(p.Age)

        # 음수 나이는 제외
        if age < 0:
            continue

        if age < 20:
            group = "0~19세"
        elif age < 40:
            group = "20~39세"
        elif age < 60:
            group = "40~59세"
        else:
            group = "60세 이상"

        age_total[group] += 1

        if p.No_show == "Yes":
            age_noshow[group] += 1
            
    print("\n연령대별 노쇼율")

    for group in ["0~19세", "20~39세", "40~59세", "60세 이상"]:
        rate = age_noshow[group] / age_total[group]
        print(f"{group:10} : {age_noshow[group]}/{age_total[group]} ({rate:.2%})")
# # 결과 출력
#     for p in patient_list:
#         p.print_info()
#--사용자 선택 메뉴--------------------------------
def print_menu():
    print('1. 성별별 분석 ')
    print('2. 예약 대기기간별 분석')
    print('3. 연령대별 분석')
    print('4. 교차분석')
    print('5. 종료')
    menu=input('메뉴 선택: ')
    return int(menu)
def analyzeByGender(g):
    #성별별 노쇼율
    male_count = 0
    male_noshow = 0

    female_count = 0
    female_noshow = 0

    for p in patient_list:
        if p.Gender == 'M':
            male_count += 1
            if p.No_show == 'Yes':    # 데이터에 맞게 'YES' 또는 'Yes' 사용
                male_noshow += 1

        elif p.Gender == 'F':
            female_count += 1
            if p.No_show == 'Yes':
                female_noshow += 1
    
    if(g=='M'):
        return [male_noshow,male_count]
    else:
        return [female_noshow,female_count]
    print("전체 남자:", male_count)
    print("노쇼한 남자:", male_noshow)
    print("남성 노쇼 비율:", male_noshow / male_count)

    print()
    
    print("전체 여자:", female_count)
    print("노쇼한 여자:", female_noshow)
    print("여성 노쇼 비율:", female_noshow / female_count)
def analyzeByWaiting(a):
    #대기 일수별 노쇼율

    group_total = {
        "0~6일": 0,
        "7~13일": 0,
        "14~20일": 0,
        "21~27일": 0,
        "28일 이상": 0
    }

    group_noshow = {
        "0~6일": 0,
        "7~13일": 0,
        "14~20일": 0,
        "21~27일": 0,
        "28일 이상": 0
        }

    for p in patient_list:

        scheduled = datetime.strptime(p.ScheduledDay[:10], "%Y-%m-%d")
        appointment = datetime.strptime(p.AppointmentDay[:10], "%Y-%m-%d")

        waiting_days = (appointment - scheduled).days

        if waiting_days < 0:
            continue

        if waiting_days < 7:
            group = "0~6일"
        elif waiting_days < 14:
            group = "7~13일"
        elif waiting_days < 21:
            group = "14~20일"
        elif waiting_days < 28:
            group = "21~27일"
        else:
            group = "28일 이상"

        group_total[group] += 1

        if p.No_show == "Yes":
            group_noshow[group] += 1
        
    if(a==1):
        return [group_noshow["0~6일"],group_total["0~6일"]]
    elif(a==2):
        return [group_noshow["7~13일"],group_total["7~13일"]]
    elif(a==3):
        return [group_noshow["14~20일"],group_total["14~20일"]]
    elif(a==4):
        return [group_noshow["21~27일"],group_total["21~27일"]]
    elif(a==5):
        return [group_noshow["28일 이상"],group_total["28일 이상"]]

def analyzeByAge(a):
    #연령별 노쇼율
    age_total = {
        "0~19세": 0,
        "20~39세": 0,
        "40~59세": 0,
        "60세 이상": 0
        }   

    age_noshow = {
        "0~19세": 0,
        "20~39세": 0,
        "40~59세": 0,
        "60세 이상": 0
        }

    for p in patient_list:

        age = int(p.Age)

        # 음수 나이는 제외
        if age < 0:
            continue

        if age < 20:
            group = "0~19세"
        elif age < 40:
            group = "20~39세"
        elif age < 60:
            group = "40~59세"
        else:
            group = "60세 이상"

        age_total[group] += 1

        if p.No_show == "Yes":
            age_noshow[group] += 1


    if(a==1):
        return [age_noshow["0~19세"],age_total["0~19세"]]
    elif(a==2):
        return [age_noshow["20~39세"],age_total["20~39세"]]
    elif(a==3):
        return [age_noshow["40~59세"],age_total["40~59세"]]
    elif(a==4):
        return [age_noshow["60세 이상"],age_total["60세 이상"]]
    
def run():
    
    with open('medical.csv', 'r', encoding='utf-8') as f:
        lines = f.readlines()
        patient_list = []
           
        for line in lines[1:]:              # [1:] → 첫 줄(헤더)은 건너뜀
            line = line.strip()               # 줄바꿈 문자 제거
            if not line:                    # 빈 줄이면 건너뜀
                continue
            values = line.split(',')        # 쉼표 기준으로 쪼개서 리스트로 만듦
            p = Patient(values[0], values[1], values[2], values[3], values[4], values[5], values[6], values[7], values[8])
            patient_list.append(p)
    while 1:
        menu=print_menu()
        if menu==1:
           g=input('분석할 성별을 입력하세요.(M/F)')
           result=analyzeByGender(g)
           print("전체",g,':',result[1])
           print("노쇼한",g,':',result[0])
           print("노쇼한",g,'비율:',result[0]/result[1])
        elif menu==2:
            a=int(input('분석할 대기일수를 입력하세요.(1: 0~6 2:7~13 3:14~20 4:21~27 5:28+)'))
            result=analyzeByWaiting(a)
            print("전체",a,':',result[1])
            print("노쇼한",a,':',result[0])
            print("노쇼한",a,'비율:',result[0]/result[1])
        elif menu==3:
            a=int(input('분석할 연령대를 입력하세요.(1: 0~19 2:20~39 3:40~59 4:60+)'))
            result = analyzeByAge(a) 
            print("전체",a,':',result[1])
            print("노쇼한",a,':',result[0])
            print("노쇼한",a,'비율:',result[0]/result[1])
        elif menu==4:
            no_showCnt=0
            totalCnt=0
            cross=input('교차 분석 할 표본을 선택하세요.(1: 성별 2: 대기일수 3:연령대)')
            cross_list = cross.split()
            for c in cross_list:
                if c == '1':
                    g=input('분석할 성별을 입력하세요.(M/F)')
                    result=analyzeByGender(g)
                    no_showCnt+=result[0]
                    totalCnt+=result[1]
                elif c == '2':
                    print("대기일수 교차분석 실행")
                    a=int(input('분석할 대기일수를 입력하세요.(1: 0~6 2:7~13 3:14~20 4:21~27 5:28+)'))
                    result=analyzeByWaiting(a)
                    no_showCnt+=result[0]
                    totalCnt+=result[1]
                elif c == '3':
                    print("연령대 교차분석 실행")
                    a=int(input('분석할 연령대를 입력하세요.(1: 0~19 2:20~39 3:40~59 4:60+)'))
                    result = analyzeByAge(a) 
                    no_showCnt+=result[0]
                    totalCnt+=result[1]
            print("전체 표본",':',totalCnt)
            print("노쇼한 표본",':',no_showCnt)
            print("노쇼한비율:",no_showCnt/totalCnt)
                            
        elif menu==5:
            
            break
        else:
            print('잘못된 명령입니다.')
        
if(__name__=='__main__'):
     run()

 

교차분석을 하기 위해서 각 함수별로 노쇼한@@@, 전체@@@를 담은 리스트를 반환하도록 했는데, 코드를 짜고 보니 사용자가 메뉴를 선택할 때마다 11만개의 데이터를 계속 순회하는 비효율적인 구조가 돼서 아쉬웠다. 

'파이썬' 카테고리의 다른 글

0713 ML/DL  (0) 2026.07.13
0710 Numpy  (0) 2026.07.10
0709 파이썬 기초 문법 복습  (0) 2026.07.09
0708 데이터 분석 및 시각화  (0) 2026.07.09
0707 Pandas  (0) 2026.07.09